6ce9ec69ad
Scrolling back and then entering keyboardselect's copy mode causes glitched text to appear when moving the cursor. This is because the keyboardselect patch is not aware of the scrollback history (term.hist), so it takes the text from the last displayed screen (term.line). Co-authored-by: Àlex Ramírez <aramirez@verbio.com>
241 lines
6.1 KiB
C
241 lines
6.1 KiB
C
void set_notifmode(int type, KeySym ksym)
|
|
{
|
|
static char *lib[] = { " MOVE ", " SEL "};
|
|
static Glyph *g, *deb, *fin;
|
|
static int col, bot;
|
|
|
|
if (ksym == -1) {
|
|
free(g);
|
|
col = term.col, bot = term.bot;
|
|
g = xmalloc(col * sizeof(Glyph));
|
|
memcpy(g, term.line[bot], col * sizeof(Glyph));
|
|
|
|
} else if (ksym == -2)
|
|
memcpy(term.line[bot], g, col * sizeof(Glyph));
|
|
|
|
if ( type < 2 ) {
|
|
char *z = lib[type];
|
|
for (deb = &term.line[bot][col - 6], fin = &term.line[bot][col]; deb < fin; z++, deb++)
|
|
deb->mode = ATTR_REVERSE,
|
|
deb->u = *z,
|
|
deb->fg = defaultfg, deb->bg = defaultbg;
|
|
} else if (type < 5)
|
|
memcpy(term.line[bot], g, col * sizeof(Glyph));
|
|
else {
|
|
for (deb = &term.line[bot][0], fin = &term.line[bot][col]; deb < fin; deb++)
|
|
deb->mode = ATTR_REVERSE,
|
|
deb->u = ' ',
|
|
deb->fg = defaultfg, deb->bg = defaultbg;
|
|
term.line[bot][0].u = ksym;
|
|
}
|
|
|
|
term.dirty[bot] = 1;
|
|
drawregion(0, bot, col, bot + 1);
|
|
}
|
|
|
|
#if SCROLLBACK_PATCH && KEYBOARDSELECT_PATCH
|
|
Glyph getglyph(Term term, int y, int x)
|
|
{
|
|
Glyph g;
|
|
int realy = y - term.scr;
|
|
if(realy >= 0) {
|
|
g = term.line[realy][x];
|
|
} else {
|
|
realy = term.histi - term.scr + y + 1;
|
|
g = term.hist[realy][x];
|
|
}
|
|
return g;
|
|
}
|
|
#endif
|
|
|
|
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);
|
|
xsetsel(getsel());
|
|
} else {
|
|
#if LIGATURES_PATCH
|
|
xdrawcursor(term.c.x, term.c.y, term.line[term.c.y][term.c.x],
|
|
term.ocx, term.ocy, term.line[term.ocy][term.ocx],
|
|
term.line[term.ocy], term.col);
|
|
#elif SCROLLBACK_PATCH && KEYBOARDSELECT_PATCH
|
|
xdrawcursor(term.c.x, term.c.y, getglyph(term, term.c.y, term.c.x),
|
|
term.ocx, term.ocy, getglyph(term, term.ocy, term.ocx));
|
|
#else
|
|
xdrawcursor(term.c.x, term.c.y, term.line[term.c.y][term.c.x],
|
|
term.ocx, term.ocy, term.line[term.ocy][term.ocx]);
|
|
#endif // LIGATURES_PATCH
|
|
}
|
|
}
|
|
|
|
void search(int selectsearch_mode, Rune *target, int ptarget, int incr, int type, TCursor *cu)
|
|
{
|
|
Rune *r;
|
|
int i, bound = (term.col * cu->y + cu->x) * (incr > 0) + incr;
|
|
|
|
for (i = term.col * term.c.y + term.c.x + incr; i != bound; i += incr) {
|
|
for (r = target; r - target < ptarget; r++) {
|
|
if (*r == term.line[(i + r - target) / term.col][(i + r - target) % term.col].u) {
|
|
if (r - target == ptarget - 1)
|
|
break;
|
|
} else {
|
|
r = NULL;
|
|
break;
|
|
}
|
|
}
|
|
if (r != NULL)
|
|
break;
|
|
}
|
|
|
|
if (i != bound) {
|
|
term.c.y = i / term.col, term.c.x = i % term.col;
|
|
select_or_drawcursor(selectsearch_mode, type);
|
|
}
|
|
}
|
|
|
|
int trt_kbdselect(KeySym ksym, char *buf, int len)
|
|
{
|
|
static TCursor cu;
|
|
static Rune target[64];
|
|
static int type = 1, ptarget, in_use;
|
|
static int sens, quant;
|
|
static char selectsearch_mode;
|
|
int i, bound, *xy;
|
|
|
|
if (selectsearch_mode & 2) {
|
|
if (ksym == XK_Return) {
|
|
selectsearch_mode ^= 2;
|
|
set_notifmode(selectsearch_mode, -2);
|
|
if (ksym == XK_Escape)
|
|
ptarget = 0;
|
|
return 0;
|
|
} else if (ksym == XK_BackSpace) {
|
|
if (!ptarget)
|
|
return 0;
|
|
term.line[term.bot][ptarget--].u = ' ';
|
|
} else if (len < 1) {
|
|
return 0;
|
|
} else if (ptarget == term.col || ksym == XK_Escape) {
|
|
return 0;
|
|
} else {
|
|
utf8decode(buf, &target[ptarget++], len);
|
|
term.line[term.bot][ptarget].u = target[ptarget - 1];
|
|
}
|
|
|
|
if (ksym != XK_BackSpace)
|
|
search(selectsearch_mode, &target[0], ptarget, sens, type, &cu);
|
|
|
|
term.dirty[term.bot] = 1;
|
|
drawregion(0, term.bot, term.col, term.bot + 1);
|
|
return 0;
|
|
}
|
|
|
|
switch (ksym) {
|
|
case -1:
|
|
in_use = 1;
|
|
cu.x = term.c.x, cu.y = term.c.y;
|
|
set_notifmode(0, ksym);
|
|
return MODE_KBDSELECT;
|
|
case XK_s:
|
|
if (selectsearch_mode & 1)
|
|
selclear();
|
|
else
|
|
selstart(term.c.x, term.c.y, 0);
|
|
set_notifmode(selectsearch_mode ^= 1, ksym);
|
|
break;
|
|
case XK_t:
|
|
selextend(term.c.x, term.c.y, type ^= 3, i = 0); /* 2 fois */
|
|
selextend(term.c.x, term.c.y, type, i = 0);
|
|
break;
|
|
case XK_slash:
|
|
case XK_KP_Divide:
|
|
case XK_question:
|
|
ksym &= XK_question; /* Divide to slash */
|
|
sens = (ksym == XK_slash) ? -1 : 1;
|
|
ptarget = 0;
|
|
set_notifmode(15, ksym);
|
|
selectsearch_mode ^= 2;
|
|
break;
|
|
case XK_Escape:
|
|
if (!in_use)
|
|
break;
|
|
selclear();
|
|
case XK_Return:
|
|
set_notifmode(4, ksym);
|
|
term.c.x = cu.x, term.c.y = cu.y;
|
|
select_or_drawcursor(selectsearch_mode = 0, type);
|
|
in_use = quant = 0;
|
|
return MODE_KBDSELECT;
|
|
case XK_n:
|
|
case XK_N:
|
|
if (ptarget)
|
|
search(selectsearch_mode, &target[0], ptarget, (ksym == XK_n) ? -1 : 1, type, &cu);
|
|
break;
|
|
case XK_BackSpace:
|
|
term.c.x = 0;
|
|
select_or_drawcursor(selectsearch_mode, type);
|
|
break;
|
|
case XK_dollar:
|
|
term.c.x = term.col - 1;
|
|
select_or_drawcursor(selectsearch_mode, type);
|
|
break;
|
|
case XK_Home:
|
|
term.c.x = 0, term.c.y = 0;
|
|
select_or_drawcursor(selectsearch_mode, type);
|
|
break;
|
|
case XK_End:
|
|
term.c.x = cu.x, term.c.y = cu.y;
|
|
select_or_drawcursor(selectsearch_mode, type);
|
|
break;
|
|
case XK_Page_Up:
|
|
case XK_Page_Down:
|
|
term.c.y = (ksym == XK_Prior ) ? 0 : cu.y;
|
|
select_or_drawcursor(selectsearch_mode, type);
|
|
break;
|
|
case XK_exclam:
|
|
term.c.x = term.col >> 1;
|
|
select_or_drawcursor(selectsearch_mode, type);
|
|
break;
|
|
case XK_asterisk:
|
|
case XK_KP_Multiply:
|
|
term.c.x = term.col >> 1;
|
|
case XK_underscore:
|
|
term.c.y = cu.y >> 1;
|
|
select_or_drawcursor(selectsearch_mode, type);
|
|
break;
|
|
default:
|
|
if (ksym >= XK_0 && ksym <= XK_9) { /* 0-9 keyboard */
|
|
quant = (quant * 10) + (ksym ^ XK_0);
|
|
return 0;
|
|
} else if (ksym >= XK_KP_0 && ksym <= XK_KP_9) { /* 0-9 numpad */
|
|
quant = (quant * 10) + (ksym ^ XK_KP_0);
|
|
return 0;
|
|
} else if (ksym == XK_k || ksym == XK_h)
|
|
i = ksym & 1;
|
|
else if (ksym == XK_l || ksym == XK_j)
|
|
i = ((ksym & 6) | 4) >> 1;
|
|
else if ((XK_Home & ksym) != XK_Home || (i = (ksym ^ XK_Home) - 1) > 3)
|
|
break;
|
|
|
|
xy = (i & 1) ? &term.c.y : &term.c.x;
|
|
sens = (i & 2) ? 1 : -1;
|
|
bound = (i >> 1 ^ 1) ? 0 : (i ^ 3) ? term.col - 1 : term.bot;
|
|
|
|
if (quant == 0)
|
|
quant++;
|
|
|
|
if (*xy == bound && ((sens < 0 && bound == 0) || (sens > 0 && bound > 0)))
|
|
break;
|
|
|
|
*xy += quant * sens;
|
|
if (*xy < 0 || ( bound > 0 && *xy > bound))
|
|
*xy = bound;
|
|
|
|
select_or_drawcursor(selectsearch_mode, type);
|
|
}
|
|
quant = 0;
|
|
return 0;
|
|
}
|