Hi All, I have been hacking Gnu Screen to add support for alt keys, and it may add some value to Screen, please check the attached patch and let me know what you think. Notice that the patch was based on the v.4.9.0 tag, but it should work in the master branch since the modified files have not been touched in years.
The patch adds support for Alt keys with '@' notation, the '@' will be the textual representation of Alt within the bind, escape, defescape and markkeys commands; the patch also adds some comments and changes the name of some variables within src/process.c file. I tested the changes manually, since I did not find any test suite, but it was not an exhaustive test since I am using only a small subset of Screen capabilities; nevertheless, the changes seems to be self-contained within the logic of the commands and process.c, which, at least for me, makes it harder to add bugs outside of the commands logic. I found some discrepancies in the coding style, some files use K&R C (src/process.c) code and other file use ISO C; Some files use Gnu C code style while other files disregard this Gnu code style. In case my patch gets accepted please let me know if I should modify the C style of the modified files. Best regards, Bryan Hernández
diff --git a/src/.gitignore b/src/.gitignore index 529960c..541cfad 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -19,3 +19,4 @@ term.h screen stamp-h.in tty.c +.gdbinit diff --git a/src/display.c b/src/display.c index 978b0a8..531ce20 100644 --- a/src/display.c +++ b/src/display.c @@ -472,7 +472,7 @@ int adapt; D_x = D_y = 0; Flush(3); ClearAll(); - debug1("we %swant to adapt all our windows to the display\n", + debug1("we %swant to adapt all our windows to the display\n", (adapt) ? "" : "don't "); /* In case the size was changed by a init sequence */ CheckScreenSize((adapt) ? 2 : 0); @@ -1209,7 +1209,7 @@ int x1, y1, xs, xe, x2, y2, bce, uselayfn; D_y = D_x = 0; return; } - /* + /* * Workaround a hp700/22 terminal bug. Do not use CD where CE * is also appropriate. */ @@ -1474,7 +1474,7 @@ int xs, ys, xe, ye, n, bce; if (D_top != ys && !(alok && dlok)) ChangeScrollRegion(ys, ye); - if (D_lp_missing && + if (D_lp_missing && (oldbot != D_bot || (oldbot == D_bot && up && D_top == ys && D_bot == ye))) { @@ -1707,7 +1707,7 @@ int jj; if (min == max) jj = ((max + 1) & 2) << 2 | ((max + 1) & 4 ? 7 : 0); else - jj = (b - min) / (max - min) << 2 | (g - min) / (max - min) << 1 | (r - + jj = (b - min) / (max - min) << 2 | (g - min) / (max - min) << 1 | (r - min) / (max - min) | (max > 3 ? 8 : 0); } return jj; @@ -1989,7 +1989,7 @@ char *msg; if (!display) return; - + if (D_blocked) return; if (!D_tcinited) @@ -3202,7 +3202,7 @@ NukePending() oldrend = D_rend; len = D_obufp - D_obuf; debug1("NukePending: nuking %d chars\n", len); - + /* Throw away any output that we can... */ # ifdef POSIX tcflush(D_userfd, TCOFLUSH); @@ -3306,7 +3306,7 @@ char *data; size = D_status_obufpos; ASSERT(len >= 0); size = write(D_userfd, D_obuf, size); - if (size >= 0) + if (size >= 0) { len -= size; if (len) @@ -3728,6 +3728,10 @@ char *data; disp_processinput(display, buf, size); } +/* + Decode input, usually a key or sequence of keys (control or alt), and process + it +*/ static void disp_processinput(display, buf, size) struct display* display; @@ -3834,10 +3838,10 @@ char *data; if ((q = D_seqh) != 0) { D_seqh = 0; - i = q[0] << 8 | q[1]; + i = q[0] << 8 | q[1]; i &= ~KMAP_NOTIMEOUT; debug1("Mapping former hit #%d - ", i); - debug2("%d(%s) - ", q[2], q + 3); + debug2("%d(%s) - ", q[2], q + 3); if (StuffKey(i)) ProcessInput2((char *)q + 3, q[2]); if (display == 0) @@ -4078,5 +4082,3 @@ char **cmdv; } #endif /* BLANKER_PRG */ - - diff --git a/src/display.h b/src/display.h index b094619..dc9687a 100644 --- a/src/display.h +++ b/src/display.h @@ -123,8 +123,8 @@ struct display int d_status_buflen; /* last message buffer len */ int d_status_lastx; /* position of the cursor */ int d_status_lasty; /* before status was displayed */ - int d_status_obuflen; /* saved obuflen */ - int d_status_obuffree; /* saved obuffree */ + int d_status_obuflen; /* saved obuflen */ + int d_status_obuffree; /* saved obuffree */ int d_status_obufpos; /* end of status position in obuf */ struct event d_statusev; /* timeout event */ struct event d_hstatusev; /* hstatus changed event */ @@ -335,4 +335,3 @@ while (0) #define HSTATUS_ALWAYS (1<<3) #endif /* SCREEN_DISPLAY_H */ - diff --git a/src/help.c b/src/help.c index 2c3a3f6..48f0a07 100644 --- a/src/help.c +++ b/src/help.c @@ -119,6 +119,8 @@ void exit_with_usage(char *myname, char *message, char *arg) /* Here come the help page routines */ extern struct comm comms[]; + +/* Global keytable */ extern struct action ktab[]; static void HelpProcess __P((char **, int *)); @@ -174,7 +176,7 @@ void display_help(char *class, struct action *ktabp) { used[n] = 0; mcom = 0; mkey = 0; - for (key = 0; key < 256 + KMAP_KEYS; key++) { + for (key = 0; key < 256 + KMAP_KEYS + 96; key++) { n = ktabp[key].nr; if (n == RC_ILLEGAL) continue; @@ -277,7 +279,7 @@ static int helppage() { /* Clear the help screen */ LClearAll(flayer, 0); - + sprintf(cbuf,"Screen key bindings, page %d of %d.", helpdata->grow / (flayer->l_height-5) + 1, helpdata->numpages); centerline(cbuf, 0); crow = 2; @@ -311,11 +313,11 @@ static int helppage() { x += helpdata->inter - !col; n = helpdata->nact[n]; buf[0] = '\0'; - for (key = 0; key < 256 + KMAP_KEYS; key++) - if (ktabp[key].nr == n && ktabp[key].args == noargs && strlen(buf) < sizeof(buf) - 7) { - strcat(buf, " "); - add_key_to_buf(buf, key); - } + for (key = 0; key < 256 + KMAP_KEYS + 96; key++) + if (ktabp[key].nr == n && ktabp[key].args == noargs && strlen(buf) < sizeof(buf) - 7) { + strcat(buf, " "); + add_key_to_buf(buf, key); + } PadStr(comms[n].name, helpdata->mcom, x, crow); x += helpdata->mcom; @@ -325,7 +327,7 @@ static int helppage() { helpdata->grow++; } - else if (helpdata->grow-2-helpdata->numrows >= helpdata->numskip + else if (helpdata->grow-2-helpdata->numrows >= helpdata->numskip && helpdata->grow-2-helpdata->numrows-helpdata->numskip < helpdata->command_bindings) { while ((n = ktabp[helpdata->command_search].nr) == RC_ILLEGAL || ktabp[helpdata->command_search].args == noargs) { if (++helpdata->command_search >= 256 + KMAP_KEYS) @@ -362,7 +364,7 @@ static void AddAction(struct action *act, int x, int y) { if (fr <= 0) return; l = strlen(comms[act->nr].name); - + if (l + 1 > fr) l = fr - 1; PadStr(comms[act->nr].name, l, x, y); @@ -411,6 +413,13 @@ static void add_key_to_buf(char *buf, int key) { strcpy(buf, "unset"); else if (key == ' ') strcpy(buf, "sp"); + else if (key >= 256 + KMAP_KEYS) { + key = key + 33 - 256 - KMAP_KEYS; + buf[0] = 'M'; + buf[1] = '-'; + buf[2] = key; + buf[3] = 0; + } #ifdef MAPKEYS else if (key >= 256) { key = key - 256 + T_CAPS; @@ -744,7 +753,7 @@ void display_bindkey(char *title, struct action *tab) { bindkeydata = (struct bindkeydata *)flayer->l_data; bindkeydata->title = title; bindkeydata->tab = tab; - + n = 0; for (i = 0; i < KMAP_KEYS+KMAP_AKEYS+kmap_extn; i++) { if (tab[i].nr != RC_ILLEGAL) @@ -839,7 +848,7 @@ static void bindkeypage() { centerline(tbuf, flayer->l_height - 2); LaySetCursor(); } - + static void BindkeyProcess(char **ppbuf, int *plen) { int done = 0; struct bindkeydata *bindkeydata; diff --git a/src/mark.c b/src/mark.c index 1e40fcb..539b01c 100644 --- a/src/mark.c +++ b/src/mark.c @@ -83,7 +83,8 @@ struct LayFuncs MarkLf = { int join_with_cr = 0; int compacthist = 0; -unsigned char mark_key_tab[256]; /* this array must be initialised first! */ +/* + 96 due to the same reasons as in ktab (process.c) */ +unsigned char mark_key_tab[256 + 96]; /* this array must be initialised first! */ static struct markdata *markdata; @@ -543,7 +544,15 @@ MarkProcess(char **inbufp, int *inlenp) continue; } } - od = mark_key_tab[(int)ch]; + + if (inbuf[0] == 033 && inlen == 1) { + ch = *pt++; + od = mark_key_tab[256 + ch - 33]; + inlen--; + } else { + od = mark_key_tab[(int)ch]; + } + rep_cnt = markdata->rep_cnt; if (od >= '0' && od <= '9' && !markdata->f_cmd.flag) { if (rep_cnt < 1001 && (od != '0' || rep_cnt != 0)) { @@ -1446,4 +1455,3 @@ FreePaster(struct paster *pa) } #endif /* COPY_PASTE */ - diff --git a/src/process.c b/src/process.c index 004b22a..de190bc 100644 --- a/src/process.c +++ b/src/process.c @@ -223,11 +223,18 @@ struct action idleaction; char **blankerprg; #endif -struct action ktab[256 + KMAP_KEYS]; /* command key translation table */ +/* Convert character to a position of Alt keys in kmap. + + First 32 chars of the ascii table are ignored since it is impossible to + combine them with alt + 1 for zero index array = 33 */ +#define ALT(character) (256 + KMAP_KEYS + character - 33) +/* 96 is the combination of Alt + any ascii key above US (0x1F) */ +struct action ktab[256 + KMAP_KEYS + 96]; /* command key translation table */ + struct kclass { struct kclass *next; char *name; - struct action ktab[256 + KMAP_KEYS]; + struct action ktab[256 + KMAP_KEYS + 96]; }; struct kclass *kclasses; @@ -483,6 +490,7 @@ char *noargs[1]; int enter_window_name_mode = 0; +/* Initialize ktab with the default key bindings */ void InitKeytab() { @@ -742,7 +750,6 @@ struct action *act; * This ProcessInput just does the keybindings and passes * everything else on to ProcessInput2. */ - void ProcessInput(ibuf, ilen) char *ibuf; @@ -760,6 +767,13 @@ int ilen; evdeq(&D_mapev); slen = ilen; s = (unsigned char *)ibuf; + + /* Send Alt+key to processinput2, instead of send each character individually. + in this way Alt+key can be processed to a command (if it has a command binded + to it) */ + if (ibuf[0] == 033 && slen == 2) + goto end; + while (ilen-- > 0) { ch = *s++; @@ -773,9 +787,10 @@ int ilen; debug3("cmp %c %c[%d]\n", ch, *D_seqp, D_seqp - D_kmaps); if (*D_seqp != ch) { - l = D_seqp[D_seqp[-D_seql-1] + 1]; + l = D_seqp[D_seqp[-1] + 1]; if (l) { + /* Set D_seqp to the next translation entry */ D_seqp += l * 2 + 4; debug1("miss %d\n", D_seqp - D_kmaps); continue; @@ -856,6 +871,7 @@ int ilen; break; } } + /* Allow more characters for multi-character entries in translation table */ if (D_seql) { debug("am in sequence -> check for timeout\n"); @@ -872,6 +888,8 @@ int ilen; } } } + + end: ProcessInput2(ibuf, slen); } @@ -881,69 +899,66 @@ int ilen; /* - * Here only the screen escape commands are handled. - */ + Handle user input until a command sequence is recognized, if no command + sequence is recognized then process the input as normal by the terminal. + This function sets screen to a state where an input is translated to commands + when the escape command (^a) is read. + Here only the screen escape commands are handled, not commands given in the + colon prompt. +*/ void ProcessInput2(ibuf, ilen) char *ibuf; int ilen; { - char *s; - int ch, slen; - struct action *ktabp; + debug1("Processinput2: ilen now %d bytes\n", ilen); + flayer = D_forecv->c_layer; + fore = D_fore; - debug1("ProcessInput2: %d bytes\n", ilen); - while (ilen && display) + /* search for ESC in ibuf (key pressed) */ + if (!D_ESCseen) { - debug1(" - ilen now %d bytes\n", ilen); - flayer = D_forecv->c_layer; - fore = D_fore; - slen = ilen; - s = ibuf; - if (!D_ESCseen) - { - while (ilen > 0) - { - if ((unsigned char)*s++ == D_user->u_Esc) - break; - ilen--; - } - slen -= ilen; - if (slen) - DoProcess(fore, &ibuf, &slen, 0); - if (--ilen == 0) - { - D_ESCseen = ktab; - WindowChanged(fore, 'E'); - } - } - if (ilen <= 0) - return; - ktabp = D_ESCseen ? D_ESCseen : ktab; - if (D_ESCseen) + for (int index = 0; index < ilen; index++) { - D_ESCseen = 0; - WindowChanged(fore, 'E'); + if ((unsigned char) ibuf[index] == D_user->u_Esc) + { + D_ESCseen = ktab; + return; + } + + if ((ilen - index) > 1 && ibuf[index] == 033 && + ALT(ibuf[index + 1]) == D_user->u_Esc) { + D_ESCseen = ktab; + return; + } } - ch = (unsigned char)*s; - /* - * As users have different esc characters, but a common ktab[], - * we fold back the users esc and meta-esc key to the Default keys - * that can be looked up in the ktab[]. grmbl. jw. - * XXX: make ktab[] a per user thing. - */ - if (ch == D_user->u_Esc) - ch = DefaultEsc; - else if (ch == D_user->u_MetaEsc) - ch = DefaultMetaEsc; + DoProcess(fore, &ibuf, &ilen, 0); + return; + } - if (ch >= 0) - DoAction(&ktabp[ch], ch); - ibuf = (char *)(s + 1); - ilen--; + /* check for alt */ + if (*ibuf == 033 && ilen > 1) + { + D_ESCseen = 0; + DoAction(&ktab[ALT(ibuf[1])], ibuf[1]); + return; } + + unsigned char ch = *ibuf; + + /* As users have different esc characters, but a common ktab[], + we fold back the users esc and meta-esc key to the Default keys + that can be looked up in the ktab[]. grmbl. jw. + XXX: make ktab[] a per user thing. */ + if (ch == D_user->u_Esc) + ch = DefaultEsc; + else if (ch == D_user->u_MetaEsc) + ch = DefaultMetaEsc; + + D_ESCseen = 0; + DoAction(&ktab[ch], ch); } void @@ -1007,6 +1022,8 @@ struct paster *pa; #endif } +/* Find the position of the 'str' command in comms. It is also use as a + predicate to know if a commands exists or not */ int FindCommnr(str) const char *str; @@ -1033,7 +1050,7 @@ char **args; { int i, n; static char *argss[] = {"no", "one", "two", "three", "four", "OOPS"}; - static char *orformat[] = + static char *orformat[] = { "%s: %s: %s argument%s required", "%s: %s: %s or %s argument%s required", @@ -1048,18 +1065,18 @@ char **args; { if (i < n) { - Msg(0, "%s: %s: at least %s argument%s required", + Msg(0, "%s: %s: at least %s argument%s required", rc_name, comms[nr].name, argss[n], n != 1 ? "s" : ""); return -1; } } - else if ((comms[nr].flags & ARGS_PLUS1) && + else if ((comms[nr].flags & ARGS_PLUS1) && (comms[nr].flags & ARGS_PLUS2) && (comms[nr].flags & ARGS_PLUS3)) { if (i != n && i != n + 1 && i != n + 2 && i != n + 3) { - Msg(0, orformat[3], rc_name, comms[nr].name, argss[n], + Msg(0, orformat[3], rc_name, comms[nr].name, argss[n], argss[n + 1], argss[n + 2], argss[n + 3], ""); return -1; } @@ -1069,7 +1086,7 @@ char **args; { if (i != n && i != n + 1 && i != n + 2) { - Msg(0, orformat[2], rc_name, comms[nr].name, argss[n], + Msg(0, orformat[2], rc_name, comms[nr].name, argss[n], argss[n + 1], argss[n + 2], ""); return -1; } @@ -1079,7 +1096,7 @@ char **args; { if (i != n && i != n + 1 && i != n + 3) { - Msg(0, orformat[2], rc_name, comms[nr].name, argss[n], + Msg(0, orformat[2], rc_name, comms[nr].name, argss[n], argss[n + 1], argss[n + 3], ""); return -1; } @@ -1089,7 +1106,7 @@ char **args; { if (i != n && i != n + 2 && i != n + 3) { - Msg(0, orformat[2], rc_name, comms[nr].name, argss[n], + Msg(0, orformat[2], rc_name, comms[nr].name, argss[n], argss[n + 2], argss[n + 3], ""); return -1; } @@ -1098,7 +1115,7 @@ char **args; { if (i != n && i != n + 1) { - Msg(0, orformat[1], rc_name, comms[nr].name, argss[n], + Msg(0, orformat[1], rc_name, comms[nr].name, argss[n], argss[n + 1], n != 0 ? "s" : ""); return -1; } @@ -1107,7 +1124,7 @@ char **args; { if (i != n && i != n + 2) { - Msg(0, orformat[1], rc_name, comms[nr].name, argss[n], + Msg(0, orformat[1], rc_name, comms[nr].name, argss[n], argss[n + 2], "s"); return -1; } @@ -1116,7 +1133,7 @@ char **args; { if (i != n && i != n + 3) { - Msg(0, orformat[1], rc_name, comms[nr].name, argss[n], + Msg(0, orformat[1], rc_name, comms[nr].name, argss[n], argss[n + 3], ""); return -1; } @@ -1212,7 +1229,7 @@ int key; { if (AclCheckPermCmd(D_user, ACL_EXEC, &comms[nr])) { - OutputMsg(0, "%s: %s: permission denied (user %s)", + OutputMsg(0, "%s: %s: permission denied (user %s)", rc_name, comms[nr].name, (EffectiveAclUser ? EffectiveAclUser : D_user)->u_name); queryflag = -1; return; @@ -1559,7 +1576,7 @@ int key; debug1("AT display %s\n", D_usertty); DoCommand(args + 1, argl + 1); if (display) - OutputMsg(0, "command from %s: %s %s", + OutputMsg(0, "command from %s: %s %s", s, args[1], args[2] ? args[2] : ""); display = NULL; flayer = 0; @@ -1579,8 +1596,8 @@ int key; continue; fore = D_fore; flayer = D_forecv->c_layer; - if (strncmp(args[0], D_usertty, n) && - (strncmp("/dev/", D_usertty, 5) || + if (strncmp(args[0], D_usertty, n) && + (strncmp("/dev/", D_usertty, 5) || strncmp(args[0], D_usertty + 5, n)) && (strncmp("/dev/tty", D_usertty, 8) || strncmp(args[0], D_usertty + 8, n))) @@ -1588,7 +1605,7 @@ int key; debug1("AT display %s\n", D_usertty); DoCommand(args + 1, argl + 1); if (display) - OutputMsg(0, "command from %s: %s %s", + OutputMsg(0, "command from %s: %s %s", s, args[1], args[2] ? args[2] : ""); display = NULL; fore = NULL; @@ -1618,10 +1635,10 @@ int key; continue; debug2("AT window %d(%s)\n", fore->w_number, fore->w_title); /* - * consider this a bug or a feature: + * consider this a bug or a feature: * while looping through windows, we have fore AND - * display context. This will confuse users who try to - * set up loops inside of loops, but often allows to do + * display context. This will confuse users who try to + * set up loops inside of loops, but often allows to do * what you mean, even when you adress your context wrong. */ i = 0; @@ -1633,7 +1650,7 @@ int key; if (fore && fore->w_layer.l_cvlist) { display = fore->w_layer.l_cvlist->c_display; - OutputMsg(0, "command from %s: %s %s", + OutputMsg(0, "command from %s: %s %s", s, args[1], args[2] ? args[2] : ""); } } @@ -1654,7 +1671,7 @@ int key; if (fore && fore->w_layer.l_cvlist) { display = fore->w_layer.l_cvlist->c_display; - OutputMsg(0, "command from %s: %s %s", + OutputMsg(0, "command from %s: %s %s", s, args[1], args[2] ? args[2] : ""); } display = NULL; @@ -1686,7 +1703,7 @@ int key; args += 2; } #endif - /* + /* * Without arguments we prompt for a destination register. * It will receive the copybuffer contents. * This is not done by RC_PASTE, as we prompt for source @@ -1703,7 +1720,7 @@ int key; break; } ch = args[0][0]; - /* + /* * With two arguments we *really* read register contents from file */ if (args[1]) @@ -1968,7 +1985,7 @@ int key; { int w, h; int what = 0; - + i = 1; if (*args && !strcmp(*args, "-w")) what = 1; @@ -2183,8 +2200,8 @@ int key; break; fore->w_wlock = n ? WLOCK_ON : WLOCK_OFF; } - /* - * user may have permission to change the writelock setting, + /* + * user may have permission to change the writelock setting, * but he may never aquire the lock himself without write permission */ if (!AclCheckPermWin(D_user, ACL_WRITE, fore)) @@ -2231,7 +2248,7 @@ int key; { #ifdef MULTIUSER if (display) /* we remove only this user */ - ACLBYTE(fore->w_mon_notify, D_user->u_id) + ACLBYTE(fore->w_mon_notify, D_user->u_id) &= ~ACLBIT(D_user->u_id); else for (i = 0; i < maxusercount; i++) @@ -2360,7 +2377,7 @@ int key; } if (args[1] == 0 && !fore) /* no window? */ break; - /* + /* * with two arguments we paste into a destination register * (no window needed here). */ @@ -2376,7 +2393,7 @@ int key; # endif /* - * measure length of needed buffer + * measure length of needed buffer */ for (ss = s = *args; (ch = *ss); ss++) { @@ -2409,7 +2426,7 @@ int key; break; } /* - * shortcut: + * shortcut: * if there is only one source and the destination is a window, then * pass a pointer rather than duplicating the buffer. */ @@ -2448,7 +2465,7 @@ int key; l += pp->len; } /* - * when called with one argument we paste our buffer into the window + * when called with one argument we paste our buffer into the window */ if (args[1] == 0) { @@ -2576,6 +2593,8 @@ int key; case RC_ESCAPE: if (*argl == 0) SetEscape(user, -1, -1); + else if (*argl == 3 && args[0][0] == '@') + SetEscape(user, ALT(args[0][1]), args[0][2]); else if (*argl == 2) SetEscape(user, (int)(unsigned char)args[0][0], (int)(unsigned char)args[0][1]); else @@ -2592,6 +2611,8 @@ int key; case RC_DEFESCAPE: if (*argl == 0) SetEscape(NULL, -1, -1); + else if (*argl == 3 && args[0][0] == '@') + SetEscape(user, ALT(args[0][1]), args[0][2]); else if (*argl == 2) SetEscape(NULL, (int)(unsigned char)args[0][0], (int)(unsigned char)args[0][1]); else @@ -2854,7 +2875,7 @@ int key; break; case RC_VERBOSE: if (!*args) - OutputMsg(0, "W%s echo command when creating windows.", + OutputMsg(0, "W%s echo command when creating windows.", VerboseCreate ? "ill" : "on't"); else if (ParseOnOff(act, &n) == 0) VerboseCreate = n; @@ -2971,7 +2992,7 @@ int key; if (n == 0) OutputMsg(0, "%s: releasing console %s", rc_name, HostName); else if (console_window) - OutputMsg(0, "%s: stealing console %s from window %d (%s)", rc_name, + OutputMsg(0, "%s: stealing console %s from window %d (%s)", rc_name, HostName, console_window->w_number, console_window->w_title); else OutputMsg(0, "%s: grabbing console %s", rc_name, HostName); @@ -3150,7 +3171,7 @@ int key; { #ifdef MULTIUSER if (display) /* we remove only this user */ - ACLBYTE(fore->w_lio_notify, D_user->u_id) + ACLBYTE(fore->w_lio_notify, D_user->u_id) &= ~ACLBIT(D_user->u_id); else for (n = 0; n < maxusercount; n++) @@ -3202,7 +3223,7 @@ int key; break; } strncpy(buf, SockPath, SockName - SockPath); - sprintf(buf + (SockName - SockPath), "%d.%s", (int)getpid(), s); + sprintf(buf + (SockName - SockPath), "%d.%s", (int)getpid(), s); free(s); if ((access(buf, F_OK) == 0) || (errno != ENOENT)) { @@ -3242,14 +3263,14 @@ int key; break; case RC_SLOWPASTE: if (*args == 0) - OutputMsg(0, fore->w_slowpaste ? + OutputMsg(0, fore->w_slowpaste ? "Slowpaste in window %d is %d milliseconds." : - "Slowpaste in window %d is unset.", + "Slowpaste in window %d is unset.", fore->w_number, fore->w_slowpaste); else if (ParseNum(act, &fore->w_slowpaste) == 0 && msgok) OutputMsg(0, fore->w_slowpaste ? "Slowpaste in window %d set to %d milliseconds." : - "Slowpaste in window %d now unset.", + "Slowpaste in window %d now unset.", fore->w_number, fore->w_slowpaste); break; case RC_MARKKEYS: @@ -3287,12 +3308,12 @@ int key; (void)ParseOnOff(act, &hardcopy_append); break; case RC_VBELL_MSG: - if (*args == 0) - { + if (*args == 0) + { char buf[256]; AddXChars(buf, sizeof(buf), VisualBellString); OutputMsg(0, "vbell_msg is '%s'", buf); - break; + break; } (void)ParseSaveStr(act, &VisualBellString); debug1(" new vbellstr '%s'\n", VisualBellString); @@ -3382,9 +3403,12 @@ int key; } else #endif - if (*argl != 1) + /* Set n to the alt key kmap position */ + if (*argl == 2 && args[0][0] == '@') + n = ALT(args[0][1]); + else if (*argl != 1) { - OutputMsg(0, "%s: bind: character, ^x, or (octal) \\032 expected.", rc_name); + OutputMsg(0, "%s: bind: character, @x, ^x, or (octal) \\032 expected.", rc_name); break; } else @@ -4644,7 +4668,7 @@ CollapseWindowlist() } void -DoCommand(argv, argl) +DoCommand(argv, argl) char **argv; int *argl; { @@ -4676,6 +4700,10 @@ int *argl; DoAction(&act, -1); } +/* + This function assign data to an action, it is usually used to save a command + that needs arguments in ktab (check InitKeytab). +*/ static void SaveAction(act, nr, args, argl) struct action *act; @@ -4739,7 +4767,7 @@ char **args; * * argc is returned. */ -int +int Parse(buf, bufl, args, argl) char *buf, **args; int bufl, *argl; @@ -4933,14 +4961,14 @@ int bufl, *argl; } void -SetEscape(u, e, me) -struct acluser *u; -int e, me; +SetEscape(user, escape, metaescape) +struct acluser *user; +int escape, metaescape; { - if (u) + if (user) { - u->u_Esc = e; - u->u_MetaEsc = me; + user->u_Esc = escape; + user->u_MetaEsc = metaescape; } else { @@ -4951,8 +4979,8 @@ int e, me; if (DefaultMetaEsc >= 0) ClearAction(&ktab[DefaultMetaEsc]); } - DefaultEsc = e; - DefaultMetaEsc = me; + DefaultEsc = escape; + DefaultMetaEsc = metaescape; if (users) { if (DefaultEsc >= 0) @@ -5038,7 +5066,7 @@ int *var; rc_name, comms[act->nr].name); return -1; } - i = 0; + i = 0; while (*p) { if (*p >= '0' && *p <= '9') @@ -5048,7 +5076,7 @@ int *var; Msg(0, "%s: %s: invalid argument. Give numeric argument.", rc_name, comms[act->nr].name); return -1; - } + } p++; } debug1("ParseNum got %d\n", i); @@ -5072,7 +5100,7 @@ int *var; rc_name, comms[act->nr].name); return -1; } - i = 0; + i = 0; while (*p) { if (*p >= '0' && *p <= '9') @@ -5091,7 +5119,7 @@ int *var; Msg(0, "%s: %s: invalid argument. Give floating point argument.", rc_name, comms[act->nr].name); return -1; - } + } p++; } if (dig == 0) @@ -5137,7 +5165,7 @@ char *str; return *s ? -1 : i; } -/* +/* * Get window number from Name or Number string. * Numbers are tried first, then names, a prefix match suffices. * Be careful when assigning numeric strings as WindowTitles. @@ -5148,7 +5176,7 @@ char *str; { int i; struct win *p; - + if ((i = WindowByNumber(str)) < 0 || i >= maxwin) { if ((p = WindowByName(str))) @@ -5171,7 +5199,7 @@ int *var; Msg(0, "%s: %s: one argument required.", rc_name, comms[act->nr].name); return -1; } - + i = WindowByNoN(*args); if (i < 0) { @@ -5211,7 +5239,7 @@ char *bname; { Msg(0, "%s: %s: argument is not %s.", rc_name, comms[act->nr].name, bname); return -1; - } + } i = base * i + c; } debug1("ParseBase got %d\n", i); @@ -5282,7 +5310,7 @@ int n; } #endif SetForeWindow(p); - Activate(fore->w_norefresh); + Activate(fore->w_norefresh); } /* @@ -5312,7 +5340,7 @@ struct win *wi; /*****************************************************************/ -/* +/* * Activate - make fore window active * norefresh = -1 forces a refresh, disregard all_norefresh then. */ @@ -5738,7 +5766,7 @@ ShowInfo() #endif sprintf(p += strlen(p), " %c%sflow", (wp->w_flow & FLOW_NOW) ? '+' : '-', - (wp->w_flow & FLOW_AUTOFLAG) ? "" : + (wp->w_flow & FLOW_AUTOFLAG) ? "" : ((wp->w_flow & FLOW_AUTO) ? "(+)" : "(-)")); if (!wp->w_wrap) sprintf(p += strlen(p), " -wrap"); if (wp->w_insert) sprintf(p += strlen(p), " ins"); @@ -6028,7 +6056,7 @@ char *data; /* dummy */ } } - + static void InputSelect() { @@ -6048,7 +6076,7 @@ char *data; /* dummy */ return; InputSetenv(buf); } - + static void SetenvFin2(buf, len, data) char *buf; @@ -6081,7 +6109,7 @@ char *arg; /* * the following options are understood by this parser: * -f, -f0, -f1, -fy, -fa - * -t title, -T terminal-type, -h height-of-scrollback, + * -t title, -T terminal-type, -h height-of-scrollback, * -ln, -l0, -ly, -l1, -l * -a, -M, -L */ @@ -6143,7 +6171,7 @@ char *fn, **av; nwin.histheight = atoi(av[0] + 2); else if (*++av) nwin.histheight = atoi(*av); - else + else --av; break; #ifdef LOGOUTOK @@ -6205,6 +6233,7 @@ char *fn, **av; } #ifdef COPY_PASTE +#define COPY_PASTE_ALT(character) (256 + character - 33) /* * CompileKeys must be called before Markroutine is first used. * to initialise the keys with defaults, call CompileKeys(NULL, mark_key_tab); @@ -6236,15 +6265,21 @@ unsigned char *array; if (*s != '=' || sl < 3) return -1; sl--; - do + do { s++; sl -= 2; value = *(unsigned char *)s++; - array[value] = key; + /* Set command in alt-command space */ + if (value == '@' && *s != '=') { + array[COPY_PASTE_ALT(*s++)] = key; + sl--; + } else { + array[value] = key; + } } while (*s == '=' && sl >= 2); - if (sl == 0) + if (sl == 0) break; if (*s++ != ':') return -1; @@ -6349,7 +6384,6 @@ int len; char *data; /* dummy */ { struct plop *pp = plop_tab + (int)(unsigned char)*buf; - if (len) { memset(buf, 0, len); @@ -6423,7 +6457,7 @@ char *data; free((char *)i); } } - + static int InputSu(w, up, name) struct win *w; @@ -6491,7 +6525,7 @@ char *data; if (buf) bzero(buf, strlen(buf)); } - + if (u->u_password != NullStr) { for (st = 0; st < 2; st++) diff --git a/src/screen.h b/src/screen.h index 4823efb..c07d874 100644 --- a/src/screen.h +++ b/src/screen.h @@ -222,13 +222,13 @@ struct msg int detachfirst; /* whether to detach remote sessions first */ } attach; - struct + struct { char duser[MAXLOGINLEN + 1]; /* username */ int dpid; /* pid of frontend */ } detach; - struct + struct { char auser[MAXLOGINLEN + 1]; /* username */ int nargs;