module patch.keyboardselect; import st; import x; import config; import patches; import core.stdc.stdio; import core.stdc.stdlib; import core.stdc.string; import deimos.X11.keysym; import deimos.X11.X : KeySym, CurrentTime; static if (isPatchEnabled!"KEYBOARDSELECT_PATCH") { __gshared { static int selectsearch_mode = 0; static TCursor cursor_state; static Glyph* saved_line = null; static int saved_col = 0; static int saved_bot = 0; } void set_notifmode(int type, KeySym ksym) { static immutable char*[2] lib = [" MOVE ".ptr, " SEL ".ptr]; static Glyph* g = null; static int col, bot; if (ksym == cast(KeySym)(-1)) { if (g) free(g); col = term.col; bot = term.bot; g = cast(Glyph*)xmalloc(col * Glyph.sizeof); memcpy(g, term.line[bot], col * Glyph.sizeof); } else if (ksym == cast(KeySym)(-2)) { if (g) memcpy(term.line[bot], g, col * Glyph.sizeof); } if (type < 2) { const(char)* z = lib[type]; for (int i = col - 6; i < col && *z; i++, z++) { term.line[bot][i].mode = GlyphAttribute.REVERSE; term.line[bot][i].u = *z; term.line[bot][i].fg = config.defaultfg; term.line[bot][i].bg = config.defaultbg; } } else if (type < 5) { if (g) memcpy(term.line[bot], g, col * Glyph.sizeof); } else { for (int i = 0; i < col; i++) { term.line[bot][i].mode = GlyphAttribute.REVERSE; term.line[bot][i].u = ' '; term.line[bot][i].fg = config.defaultfg; term.line[bot][i].bg = config.defaultbg; } term.line[bot][0].u = cast(Rune)ksym; } term.dirty[bot] = 1; drawregion(0, bot, col, bot + 1); } Glyph getglyph(int y, int x) { static if (isPatchEnabled!"SCROLLBACK_PATCH") { int realy = y - term.scr; if (realy >= 0) { return term.line[realy][x]; } else { realy = term.histi - term.scr + y + 1; return term.hist[realy][x]; } } else { return term.line[y][x]; } } void select_or_drawcursor(int selectsearch_mode, int type) { int done = 0; if (selectsearch_mode & 1) { selextend(term.c.x, term.c.y, type, done); setsel(getsel(), CurrentTime); } else { xdrawcursor(term.c.x, term.c.y, getglyph(term.c.y, term.c.x), term.ocx, term.ocy, getglyph(term.ocy, term.ocx)); } } extern(C) void keyboard_select(const(Arg)* dummy) { selectsearch_mode ^= 1; set_notifmode(selectsearch_mode, cast(KeySym)(-1)); if (selectsearch_mode == 0) { set_notifmode(4, cast(KeySym)(-2)); } select_or_drawcursor(selectsearch_mode, SelType.REGULAR); } int trt_kbdselect(KeySym ksym, char* buf, int len) { static TCursor cu; int i, bound; if (selectsearch_mode == 0) return 0; switch (ksym) { case XK_Escape: selectsearch_mode = 0; set_notifmode(4, cast(KeySym)(-2)); return 0; case XK_Return: selectsearch_mode ^= 1; set_notifmode(selectsearch_mode, cast(KeySym)(-1)); select_or_drawcursor(selectsearch_mode, SelType.REGULAR); return 0; case XK_h: case XK_Left: if (term.c.x > 0) { term.c.x--; select_or_drawcursor(selectsearch_mode, SelType.REGULAR); } return 0; case XK_l: case XK_Right: if (term.c.x < term.col - 1) { term.c.x++; select_or_drawcursor(selectsearch_mode, SelType.REGULAR); } return 0; case XK_j: case XK_Down: if (term.c.y < term.bot) { term.c.y++; select_or_drawcursor(selectsearch_mode, SelType.REGULAR); } return 0; case XK_k: case XK_Up: if (term.c.y > term.top) { term.c.y--; select_or_drawcursor(selectsearch_mode, SelType.REGULAR); } return 0; case XK_w: // Word forward while (term.c.x < term.col - 1 && getglyph(term.c.y, term.c.x).u == ' ') { term.c.x++; } while (term.c.x < term.col - 1 && getglyph(term.c.y, term.c.x).u != ' ') { term.c.x++; } select_or_drawcursor(selectsearch_mode, SelType.REGULAR); return 0; case XK_b: // Word backward while (term.c.x > 0 && getglyph(term.c.y, term.c.x).u == ' ') { term.c.x--; } while (term.c.x > 0 && getglyph(term.c.y, term.c.x).u != ' ') { term.c.x--; } select_or_drawcursor(selectsearch_mode, SelType.REGULAR); return 0; case XK_0: case XK_Home: term.c.x = 0; select_or_drawcursor(selectsearch_mode, SelType.REGULAR); return 0; case XK_dollar: case XK_End: term.c.x = term.col - 1; select_or_drawcursor(selectsearch_mode, SelType.REGULAR); return 0; default: return 0; } } void toggle_winmode(int flag) { term.mode ^= flag; } }