/* * File: guic-win.cc * Created by: ennewalker on Sat Jan 5 01:33:53 2008 UTC * * Modified for Crawl Reference by $Author: j-p-e-g $ on $Date: 2008-03-07 $ */ #include "AppHdr.h" #include #include #include #ifdef USE_X11 //Sys dep #include #include #include #include #include #include #include #endif #include "cio.h" #include "enum.h" #include "externs.h" #include "guic.h" #include "libutil.h" /* * Tile related stuff */ #ifdef USE_TILE #include "tiles.h" static Display *display=NULL; static int screen; static int x11_keypress(XKeyEvent *xev); static void x11_check_exposure(XEvent *xev); extern WinClass *win_main; void GetNextEvent(int *etype, int *key, bool *shift, bool *ctrl, int *x1, int *y1, int *x2, int *y2) { XEvent xev; while (true) { XNextEvent(display, &xev); if (xev.type == KeyPress) { *etype = EV_KEYIN; *key = x11_keypress(&(xev.xkey)); break; } else if (xev.type == Expose) { x11_check_exposure(&xev); } else if (xev.type == ConfigureNotify) { win_main->ox = xev.xconfigure.x; win_main->oy = xev.xconfigure.y; break; } else if (xev.type == ButtonPress) { *etype = EV_BUTTON; int button = xev.xbutton.button; *shift = (xev.xkey.state & ShiftMask) ? true : false; *ctrl = (xev.xkey.state & ControlMask) ? true : false; *x1 = xev.xbutton.x; *y1 = xev.xbutton.y; if (button == 3) button = 2; else if (button == 2) button = 3; *key = button; break; } else if (xev.type == MotionNotify || xev.type == EnterNotify) { *etype = EV_MOVE; *x1 = xev.xbutton.x; *y1 = xev.xbutton.y; break; } else if (xev.type == LeaveNotify) { *etype = EV_MOVE; *x1 = -100; *y1 = -100; break; } else if (xev.type == ButtonRelease) { *etype = EV_UNBUTTON; int button = xev.xbutton.button; if (button == 3) button = 2; else if (button == 2) button = 3; *x1 = xev.xbutton.x; *y1 = xev.xbutton.y; *key = button; break; } } } char *my_getenv(const char *envname, const char *def) { const char *result = getenv(envname); if (!result) result = def; return (char *)result; } int my_getenv_int(const char *envname, int def) { const char *rstr = getenv(envname); if (!rstr) return def; return atoi(rstr); } extern WinClass *win_main; extern TextRegionClass *region_tip; extern TextRegionClass *region_crt; void update_tip_text(const char *tip) { const unsigned int tip_size = 512; static char old_tip[tip_size]; char new_tip[tip_size]; if (strncmp(old_tip, tip, tip_size) == 0) return; const bool is_main_screen = (win_main->active_layer == 0); const unsigned int height = is_main_screen ? region_tip->my : 1; const unsigned int width = is_main_screen ? region_tip->mx : region_crt->mx; strncpy(new_tip, tip, tip_size); strncpy(old_tip, new_tip, tip_size); if (is_main_screen) region_tip->clear(); char *next_tip = new_tip; for (unsigned int i = 0; next_tip && i < height; i++) { char *this_tip = next_tip; // find end of line char *pc = strchr(next_tip, '\n'); if (pc) { *pc = 0; next_tip = pc + 1; } else next_tip = 0; if (strlen(this_tip) > width) { // try to remove inscriptions char *ins = strchr(this_tip, '{'); if (ins && ins[-1] == ' ') ins--; if (ins && (ins - this_tip <= (int)width)) { *ins = 0; } else { // try to remove state, e.g. "(worn)" char *state = strchr(this_tip, '('); if (state && state[-1] == ' ') state--; if (state && (state - this_tip <= (int)width)) { *state = 0; } else { // if nothing else... this_tip[width] = 0; this_tip[width-1] = '.'; this_tip[width-2] = '.'; } } } if (is_main_screen) { region_tip->cgotoxy(1, 1 + i); region_tip->addstr(this_tip); region_tip->make_active(); } else { ASSERT(i == 0); textattr(WHITE); cgotoxy(1, get_number_of_lines() + 1); cprintf("%s", this_tip); clear_to_end_of_line(); } } } void TileDrawDungeonAux() { } #endif /* USE_TILE */ /* X11 */ void x11_check_exposure(XEvent *xev) { int sx, sy, ex, ey; sx = xev->xexpose.x; ex = xev->xexpose.x + (xev->xexpose.width) - 1; sy = xev->xexpose.y; ey = xev->xexpose.y + (xev->xexpose.height) - 1; if (xev->xany.window != win_main->win) return; win_main->redraw(sx,sy,ex,ey); } /* X11 */ // This routine is taken from Angband main-x11.c int x11_keypress(XKeyEvent *xev) { #define IsSpecialKey(keysym) \ ((unsigned)(keysym) >= 0xFF00) const unsigned int ck_table[9] = { CK_END, CK_DOWN, CK_PGDN, CK_LEFT, CK_INSERT, CK_RIGHT, CK_HOME, CK_UP, CK_PGUP }; int dir, base; int n; bool mc, ms, ma; unsigned int ks1; XKeyEvent *ev = (XKeyEvent*)(xev); KeySym ks; char buf[256]; n = XLookupString(ev, buf, 125, &ks, NULL); buf[n] = '\0'; if (IsModifierKey(ks)) return 0; /* Extract "modifier flags" */ mc = (ev->state & ControlMask) ? true : false; ms = (ev->state & ShiftMask) ? true : false; ma = (ev->state & Mod1Mask) ? true : false; /* Normal keys */ if (n && !IsSpecialKey(ks)) { buf[n] = 0; // Hack Ctrl + [0-9] etc. if (mc && ((ks >= '0' && ks <= '9') || buf[0] >= ' ')) return 1024 | ks; if (!ma) return buf[0]; /* Alt + ? */ return 2048|buf[0]; } /* Hack -- convert into an unsigned int */ ks1 = (uint)(ks); /* Handle a few standard keys (bypass modifiers) XXX XXX XXX */ base = dir = 0; switch (ks1) { case XK_Escape: base = 0x1b; break; case XK_Return: base = '\r'; break; case XK_Tab: base = '\t'; break; case XK_Delete: case XK_BackSpace: base = '\010'; break; // for menus case XK_Down: return CK_DOWN; case XK_Up: return CK_UP; case XK_Left: return CK_LEFT; case XK_Right: return CK_RIGHT; // Keypad case XK_KP_1: case XK_KP_End: dir = 1; break; case XK_KP_2: case XK_KP_Down: dir = 2; break; case XK_KP_3: case XK_KP_Page_Down: dir = 3; break; case XK_KP_6: case XK_KP_Right: dir = 6; break; case XK_KP_9: case XK_KP_Page_Up: dir = 9; break; case XK_KP_8: case XK_KP_Up: dir = 8; break; case XK_KP_7: case XK_KP_Home: dir = 7; break; case XK_KP_4: case XK_KP_Left: dir = 4; break; case XK_KP_5: dir = 5; break; } //Handle keypad first if (dir != 0) { int result = ck_table[dir-1]; if (ms) result += CK_SHIFT_UP - CK_UP; if (mc) result += CK_CTRL_UP - CK_UP; return result; } if (base != 0) { if (ms) base |= 1024; if (mc) base |= 2048; if (ma) base |= 4096; return base; } //Hack Special key if (ks1 >= 0xff00) { base = 512 + ks1 - 0xff00; if (ms) base |= 1024; if (mc) base |= 2048; if (ma) base |= 4096; return base; } return 0; } void libgui_init_sys() { GuicInit(&display, &screen); } void libgui_shutdown_sys() { GuicDeinit(); } void update_screen() { XFlush(display); } int kbhit() { XEvent xev; if (XCheckMaskEvent(display, KeyPressMask | ButtonPressMask, &xev)) { XPutBackEvent(display, &xev); return 1; } return 0; } void delay( unsigned long time ) { usleep( time * 1000 ); } /* Convert value to string */ int itoa(int value, char *strptr, int radix) { unsigned int bitmask = 32768; int ctr = 0; int startflag = 0; if (radix == 10) { sprintf(strptr, "%i", value); } else if (radix == 2) /* int to "binary string" */ { while (bitmask) { if (value & bitmask) { startflag = 1; sprintf(strptr + ctr, "1"); } else if (startflag) { sprintf(strptr + ctr, "0"); } bitmask = bitmask >> 1; if (startflag) ctr++; } if (!startflag) /* Special case if value == 0 */ sprintf((strptr + ctr++), "0"); strptr[ctr] = (char) NULL; } return (0); /* Me? Fail? Nah. */ } // Convert string to lowercase. char *strlwr(char *str) { unsigned int i; for (i = 0; i < strlen(str); i++) str[i] = tolower(str[i]); return (str); } int stricmp( const char *str1, const char *str2 ) { return (strcmp(str1, str2)); }