From 9ce5b286eb67b2a8a9431f1aa8a3ee4c2d543085 Mon Sep 17 00:00:00 2001 From: Michael Jennings Date: Wed, 22 May 2002 15:38:35 +0000 Subject: [PATCH] Wed May 22 11:37:19 2002 Michael Jennings (mej) Latest Escreen work from Azundris . SVN revision: 6270 --- ChangeLog | 4 + {src => doc}/README.Escreen | 75 ++++-- doc/escreen.cfg | 132 ++++++++++ src/actions.c | 2 +- src/command.c | 273 +++++++++++++++++++-- src/libscream.c | 475 +++++++++++++++++++++++++++--------- src/menus.c | 31 ++- src/menus.h | 1 + src/options.c | 14 +- src/options.h | 1 + src/pixmap.c | 107 ++------ src/scream.h | 21 +- src/screamcfg.h | 18 +- src/screen.c | 18 +- src/screen.h | 3 + src/startup.c | 2 +- 16 files changed, 893 insertions(+), 284 deletions(-) rename {src => doc}/README.Escreen (83%) create mode 100644 doc/escreen.cfg diff --git a/ChangeLog b/ChangeLog index a07a2fc..ba97c1c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4663,3 +4663,7 @@ Wed May 22 09:16:55 2002 Michael Jennings (mej) Touch-ups to help info. ---------------------------------------------------------------------- +Wed May 22 11:37:19 2002 Michael Jennings (mej) + +Latest Escreen work from Azundris . +---------------------------------------------------------------------- diff --git a/src/README.Escreen b/doc/README.Escreen similarity index 83% rename from src/README.Escreen rename to doc/README.Escreen index a1cee8d..62a2d60 100644 --- a/src/README.Escreen +++ b/doc/README.Escreen @@ -47,18 +47,13 @@ a menu of screen-related actions. If you normally don't use a button-bar, Escreen will create one for you. Otherwise, it will add buttons to your existing bar. +* .screenrc, $SCREENRC, [/usr/local]/etc/screenrc and $SYSSCREENRC are + supported. +* Eterm-buttons are supported (left click on display-name to activate + the display, middle to close it, right to rename it). -5 - What's new? - -* Support for ".screenrc". This was temporarily disabled to aid in - debugging and has now returned in conjunction with - -* Escreen accepting non-default key setups and - -* renaming of displays - -* sending statements to screen (^A: in the default setup) with +* Sending statements to screen (^A: in the default setup) with tab-completion * support for screen command-line options: @@ -68,14 +63,27 @@ existing bar. escape-character in the ECHO action; Escreen will remap it to whatever is actually used in the session) -* rewrite of key parts for enhanced compatibility - * alert boxes for messages from screen * support for SSH-tunneling through firewalls +5 - What's new? + +* Entering and exiting copy mode no longer produces a dialog box. + Just too bloody annoying, that. + +* SCREENRC, SYSSCREENRC, .../etc/screenrc support (thanks mej) + +* Easy-to-remember key-layout (optional, see below) + +* Comes up much faster + +* You can pass arbitrary paramters to screen/scream now + + + 6 - What should I expect in the future? (TODO) * Limited support for scrolling. screen doesn't give us all the info @@ -88,15 +96,6 @@ existing bar. 9 - FAQ -Q I don't see any buttons when I connect to a remote screen! - -A Some Debian-users reported this before, and it is presumed to be a - problem with the terminfo-data. Call up Eterm (or xterm, or whatnot). - *Then* call up "screen" from inside that terminal. Is the last line - inverted? If it isn't, something is seriously weird with your setup, - and it's not a problem in Escreen. Sorry. : ( - 2002/05/13 rewritten code should handle most of these cases - Q ^A does funny things! A Well, yes. ^A talks to the screen program. Put a line @@ -116,11 +115,31 @@ A You probably already have changed the magic escape key to something Er, you *did* hold Control, then press A, rather then typing a ^ and an A, right? -Q I'd like for the button labels to be in a different colour. +Q But I don't like all this control-whatever stuff, can I have easier + to remember bindings? -A At this time, the labels follow the general (text) colours. - You will be able to define colours for (foreground|background|active|bell) - windows' labels in later releases. +A Sure. Eterm is The Configurable Terminal, after all. A pret-a-porter + example that you can simply add to your theme.cfg file (or %include + from it) lives in escreen.cfg -- enjoy. + +Q Escreen changes the escape on the remote box to the same thing as on + the local box, does it have to? + +A You can always override the escapes like so: + + Eterm -U user@host.com/-e^Xy + + Where ^X is the escape and y the literal (man screen). + +Q I don't see any buttons when I connect to a remote screen! + +A Some Debian-users reported this before, and it is presumed to be a + problem with the terminfo-data. Call up Eterm (or xterm, or whatnot). + *Then* call up "screen" from inside that terminal. Is the last line + inverted? If it isn't, something is seriously weird with your setup, + and it's not a problem in Escreen. Sorry. : ( + 2002/05/13 rewritten code should handle most of these cases + 2002/05/18 rewritten code should handle even more of these cases : ) Q Escreen opens, then closes again. @@ -137,6 +156,12 @@ Q Escreen works, except when I use -Z to tunnel through a firewall? A Try to manually ssh to the firewall, see how long that takes. Then, tune the -Z option accordingly (cf man Eterm). +Q I'd like for the button labels to be in a different colour. + +A At this time, the labels follow the general (text) colours. + You will be able to define colours for (foreground|background|active|bell) + windows' labels in later releases. + Q "screen" support rocks! Can we have it in konsole/multi-gnome-terminal? A I will not attempt anything like that before I am happy with Escreen. diff --git a/doc/escreen.cfg b/doc/escreen.cfg new file mode 100644 index 0000000..ec6b43b --- /dev/null +++ b/doc/escreen.cfg @@ -0,0 +1,132 @@ + + + # key-bindings for Escreen. + # for those who don't like the traditional ones (as used by the "screen" + # program). you may use the control variety, the alt variety, or both. + # you can copy the statements you like into the "action" context of your + # Eterm theme, or you could include this file via %include "escreen.cfg" + # See "man Eterm" for more information. + # 2002/05/19 Azundris + + # CONTROL VARIETY ######################################################### + + # ctrl-left -> previous display, ctrl-right -> next display + bind ctrl Left to echo ^Ap + bind ctrl Right to echo ^An + + # ctl-pg_up -> previous display, ctl-pg_dn -> next display (Galeon-like) + bind ctrl Prior to echo ^Ap + bind ctrl Next to echo ^An + + # no ctrl-up/down; we shouldn't steal that from the app. + + # ctl-space -> toggle between last two displays + bind ctrl space to echo ^A^A + + # ctrl-1..ctrl-0 -> display_0..display_9 + bind ctrl 0x31 to echo ^A0 + bind ctrl 0x32 to echo ^A1 + bind ctrl 0x33 to echo ^A2 + bind ctrl 0x34 to echo ^A3 + bind ctrl 0x35 to echo ^A4 + bind ctrl 0x36 to echo ^A5 + bind ctrl 0x37 to echo ^A6 + bind ctrl 0x38 to echo ^A7 + bind ctrl 0x39 to echo ^A8 + bind ctrl 0x30 to echo ^A9 + + # ALT VARIETY ############################################################# + + # alt-left -> previous display, alt-right -> next display + bind alt Left to echo ^Ap + bind alt Right to echo ^An + + # alt-up -> previous region, alt-down -> next region + bind alt Down to echo ^A\t + + # alt-pg_up -> previous display, alt-pg_dn -> next display + bind alt Prior to echo ^Ap + bind alt Next to echo ^An + + # alt-space -> toggle between last two displays + bind alt space to echo ^A^A + + # alt-1..alt-0 -> display_0..display_9 + bind alt 0x31 to echo ^A0 + bind alt 0x32 to echo ^A1 + bind alt 0x33 to echo ^A2 + bind alt 0x34 to echo ^A3 + bind alt 0x35 to echo ^A4 + bind alt 0x36 to echo ^A5 + bind alt 0x37 to echo ^A6 + bind alt 0x38 to echo ^A7 + bind alt 0x39 to echo ^A8 + bind alt 0x30 to echo ^A9 + + # FUNCTION KEYS ########################################################### + + # F1..F10 -> display_0..display_9 + bind F1 to echo ^A0 + bind F2 to echo ^A1 + bind F3 to echo ^A2 + bind F4 to echo ^A3 + bind F5 to echo ^A4 + bind F6 to echo ^A5 + bind F7 to echo ^A6 + bind F8 to echo ^A7 + bind F9 to echo ^A8 + bind F10 to echo ^A9 + + # alt F4 -> close display + bind alt F4 to echo ^Ak + + # MISC STUFF ############################################################## + + # DISPLAY + + # alt-n -> new display + bind alt n to echo ^Ac + + # alt-r -> rename display + bind alt r to echo ^AA + + # alt-c -> close display + bind alt c to echo ^Ak + + # alt-m -> monitor display + bind alt m to echo ^AM + + # alt-b -> backlog + bind alt b to echo ^A^[ + + + # REGION + + # alt-s -> split + bind alt s to echo ^AS + + # alt-u -> unsplit + bind alt u to echo ^AQ + + # alt-o -> other region + bind alt o to echo ^A^I + + # alt-k -> kill region + bind alt k to echo ^AX + + # ^Tab -> next region + bind ctrl Tab to echo ^A^I + + + + # OTHER + + # alt-S -> statement + bind alt shift S to echo ^A: + + # alt-R -> reset + bind alt shift R to echo ^AZ + + + + # ENDS #################################################################### diff --git a/src/actions.c b/src/actions.c index bf52cb1..2379ea9 100644 --- a/src/actions.c +++ b/src/actions.c @@ -61,7 +61,7 @@ action_handle_echo(event_t *ev, action_t *action) REQUIRE_RVAL(action->param.string != NULL, 0); #ifdef ESCREEN if (TermWin.screen_mode && TermWin.screen) /* translate escapes */ - ns_screen_command(TermWin.screen, action->param.string); + ns_parse_screen_interactive(TermWin.screen, action->param.string); else #endif tt_write((unsigned char *) action->param.string, strlen(action->param.string)); diff --git a/src/command.c b/src/command.c index fdd93b8..5b1a4a1 100644 --- a/src/command.c +++ b/src/command.c @@ -1131,7 +1131,8 @@ clean_exit(void) font_cache_clear(); eterm_font_list_clear(); # ifdef PIXMAP_SUPPORT - FOREACH_IMAGE(free_eterm_image(&(images[idx]));); + FOREACH_IMAGE(free_eterm_image(&(images[idx])); + ); # endif for (i = 0; i < NRS_COLORS; i++) { if (rs_color[i]) { @@ -2101,18 +2102,6 @@ run_command(char **argv) ttymode_t tio; int ptyfd; -#ifdef NS_DEBUG - { - char **a = argv; - if (a) { - while (*a) { - fprintf(stderr, NS_PREFIX "run_command: %s\n", *a); - a++; - } - } - } -#endif - /* Save and then give up any super-user privileges */ privileges(IGNORE); @@ -2506,9 +2495,23 @@ upd_disp(void *xd, int n, int flags, char *name) /* display a status line the screen program sent us */ int err_msg(void *xd, int err, char *msg) -{ - if (strlen(msg)) - menu_dial(NULL, msg, 0, NULL, NULL); +{ /* there are certain things that would make sense if we were displaying + a status-line; they do not, however, warrant an alert-box, so we drop + them here. */ + + char *sc[] = { "Copy mode", "Bell in" }; + int n, nsc = sizeof(sc) / sizeof(char *); + + if (strlen(msg)) { + for (n = 0; n < nsc; n++) { + if (!strncmp(msg, sc[n], strlen(sc[n]))) { + break; + } + } + if (n >= nsc) { + menu_dial(NULL, msg, 0, NULL, NULL); + } + } return NS_SUCC; } @@ -2547,6 +2550,194 @@ exe_prg(void *xd, char **argv) return run_command(argv); } + + +#define DIRECT_MASK (~(RS_Cursor|RS_Select|RS_fontMask)) +#define COLOUR_MASK (RS_fgMask|RS_bgMask) +#define DIRECT_SET_SCREEN(x,y,fg,bg) (screen.text[ys+y])[x]=fg; (screen.rend[ys+y])[x]=bg&DIRECT_MASK; +#define CLEAR (1<<16) + +void +direct_write_screen(int x, int y, char *fg, rend_t bg) +{ + int ys = TermWin.saveLines - TermWin.view_start; + text_t *t = screen.text[ys + y]; + rend_t *r = screen.rend[ys + y]; + if (!fg) + return; + while (*fg && (x >= 0) && (x < TermWin.ncol)) { + t[x] = *(fg++); + r[x++] = bg & DIRECT_MASK; + } +} + + + +void +bosconian(int n) +{ + int x, y; + int ys = TermWin.saveLines - TermWin.view_start; + while (n--) { + for (y = 0; y < TermWin.nrow; y++) { + text_t *t = screen.text[ys + y]; + rend_t *r = screen.rend[ys + y]; + for (x = 0; x < TermWin.ncol; x++) { + t[x] = random() & 0xff; + r[x] = random() & COLOUR_MASK; + } + } + scr_refresh(FAST_REFRESH); + } +} + + + +void +unbosconian(void) +{ + int x, y; + int ys = TermWin.saveLines - TermWin.view_start; + rend_t bg; + do { + bg = CLEAR; + for (y = 0; (bg == CLEAR) && y < TermWin.nrow; y++) { + text_t *t = screen.text[ys + y]; + rend_t *r = screen.rend[ys + y]; + for (x = 0; (bg == CLEAR) && x < TermWin.ncol; x++) { + if (r[x] != CLEAR) { + bg = r[x]; + } + } + } + if (bg != CLEAR) { + for (y = 0; y < TermWin.nrow; y++) { + text_t *t = screen.text[ys + y]; + rend_t *r = screen.rend[ys + y]; + for (x = 0; x < TermWin.ncol; x++) { + if (r[x] == bg) { + r[x] = CLEAR; + t[x] = ' '; + } + } + } + scr_refresh(FAST_REFRESH); + } + } while (bg != CLEAR); +} + + + +void +matrix(int n) +{ + int x, y, w, f; + int ys = TermWin.saveLines - TermWin.view_start; + text_t *s = malloc(TermWin.ncol); + text_t *t, *t2; + rend_t *r, *r2; + + if (!s) { + puts("fail"); + return; + } + + memset(s, 0, TermWin.ncol); +#define MATRIX_HI CLEAR +#define MATRIX_LO ((4<<8)|CLEAR) + + while (n--) { + for (x = 0; x < TermWin.ncol; x++) { + if (!(random() & 3)) { + if ((y = s[x])) { + w = random() & 15; + } else { + w = 0; + } + t = screen.text[ys + y]; + r = screen.rend[ys + y]; + + switch (w) { + case 0: /* restart */ + if (s[x]) { + r[x] = MATRIX_LO; + s[x] = 0; + t = screen.text[ys]; + r = screen.rend[ys]; + } + r[x] = MATRIX_HI; + t[x] = random() & 0xff; + s[x]++; + /* fall-through */ + + case 1: /* continue */ + case 2: + case 3: + f = random() & 7; + while (f--) { + if (y < TermWin.nrow - 1) { + t2 = screen.text[ys + y + 1]; + r2 = screen.rend[ys + y + 1]; + t2[x] = t[x]; + r2[x] = r[x]; + s[x]++; + y++; + } else { + s[x] = 0; + f = 0; + } + r[x] = MATRIX_LO; + t[x] = random() & 0xff; + if (f) { + scr_refresh(FAST_REFRESH); + t = screen.text[ys + y]; + r = screen.rend[ys + y]; + } + } + break; + + default: /* hold */ + t[x] = random() & 0xff; + } + } + } + scr_refresh(FAST_REFRESH); + } + free(s); +} + + + +/* do whatever for ms milli-seconds */ +int +waitstate(void *xd, int ms) +{ + int y = 1; + time_t dur = (time_t) (ms / 1000), fin = dur + time(NULL); + + if (!(random() & 7)) { + if (!(random() & 3)) { + matrix(31); + unbosconian(); + } + bosconian(4); + unbosconian(); + } + + direct_write_screen(0, y++, " **** COMMODORE 64 BASIC V2 ****", (0 << 8) | CLEAR); + direct_write_screen(0, y++, " 64K RAM SYSTEM 38911 BASIC BYTES FREE", (0 << 8) | CLEAR); + y += 2; + direct_write_screen(0, y++, "READY.", (0 << 8) | CLEAR); + screen.row = y; + screen.col = 0; + + scr_refresh(FAST_REFRESH); + + sleep(dur); + + return 0; +} + #endif @@ -2579,6 +2770,8 @@ init_command(char **argv) ns_register_txt(efuns, inp_text); ns_register_inp(efuns, inp_dial); ns_register_tab(efuns, menu_tab); + + ns_register_fun(efuns, waitstate); #endif /* Initialize the command connection. This should be called after @@ -2613,16 +2806,38 @@ init_command(char **argv) button_t *button; menu_t *m; menuitem_t *i; + if (rs_delay >= 0) { + TermWin.screen->delay = rs_delay; /* more flexible ways later */ + } if ((m = menu_create(NS_MENU_TITLE))) { - char *sc[] = { "New", "\x01\x03", "Close", "\x01k" }; + char *sc[] = { + /* display functions */ + "New", "\x01:screen\r", + "New ...", "\x01\x03\x01\x41", + "Backlog ...", "\x01\x1b", + "Monitor", "\x01M", + "Close", "\x01k", + "-", "", + /* region functions */ + "Split", "\x01S", + "Unsplit", "\x01Q", + "Prvs region", NS_SCREEN_PRVS_REG, + "Next region", "\x01\t", + "Kill region", "\x01X", + "-", "", + /* screen functions */ + "Reset", NS_SCREEN_INIT, + "Statement", "\x01:", + "-", "" + }; int n, nsc = sizeof(sc) / sizeof(char *); if (menu_list) { for (n = 0; n < menu_list->nummenus; n++) { /* blend in w/ l&f */ -#ifdef NS_DEBUG - fprintf(stderr, NS_PREFIX "font: %d: %p\n", n, menu_list->menus[n]->font); -#endif if (menu_list->menus[n]->font) { +#ifdef NS_DEBUG + fprintf(stderr, NS_PREFIX "font: %d: %p\n", n, menu_list->menus[n]->font); +#endif m->font = menu_list->menus[n]->font; m->fwidth = menu_list->menus[n]->fwidth; m->fheight = menu_list->menus[n]->fheight; @@ -2635,11 +2850,22 @@ init_command(char **argv) } for (n = 0; n < (nsc - 1); n += 2) { - if ((i = menuitem_create(sc[n]))) { + if (!strcmp(sc[n], "-")) { /* separator */ + if ((i = menuitem_create(NULL))) { + menu_add_item(m, i); + menuitem_set_action(i, MENUITEM_SEP, NULL); + } + } /* menu entry */ + else if ((i = menuitem_create(sc[n]))) { + menuitem_set_action(i, n && strcmp(sc[n + 1], NS_SCREEN_INIT) + && strcmp(sc[n + 1], NS_SCREEN_PRVS_REG) ? MENUITEM_ECHO : MENUITEM_LITERAL, sc[n + 1]); # ifdef NS_DEBUG - fprintf(stderr, NS_PREFIX "register %s (%d)\n", &sc[n + 1][1], *sc[n + 1]); + { + char buf[64]; + sprintf(buf, NS_PREFIX "escreen_menu: registered %s as", sc[n]); + ns_desc_string(i->action.string, buf); + } # endif - menuitem_set_action(i, MENUITEM_ECHO, sc[n + 1]); menu_add_item(m, i); } } @@ -3054,6 +3280,7 @@ main_loop(void) check_pixmap_change(0); } #endif + do { while ((ch = cmd_getc()) == 0); /* wait for something */ if (ch >= ' ' || ch == '\t' || ch == '\n' || ch == '\r') { diff --git a/src/libscream.c b/src/libscream.c index 82882a3..a46a3fc 100644 --- a/src/libscream.c +++ b/src/libscream.c @@ -12,6 +12,8 @@ * 2002/05/04 Azundris support for esoteric screens, thanks to Till * 2002/05/12 Azundris edit display names, send statement, tab completion * 2002/05/13 Azundris ssh tunnel through firewall + * 2002/05/17 Azundris supports systemwide screenrc (thanks mej) + * 2002/05/18 Azundris remote handling improved (thanks tillsan, tfing) ***************************************************************************/ @@ -42,6 +44,26 @@ +/* test if we have a valid callback for function-type "e". + !p a variable of the "_ns_efuns *" type. will contain a pointer to + an efun struct containing a function pointer to the requested function + if such a struct exists, or NULL, if it doesn't exist + s a variable of the "_ns_sess *" type, or NULL (see ns_get_efuns()) + d a variable of the "_nd_disp *" type, or NULL (see ns_get_efuns()) + e the name of an element of "_ns_efuns" + !<- conditional execution of next (compound-) statement (which would + normally be (p)->(e)(...), the call of the function e). + */ +#define NS_EFUN_EXISTS(p,s,d,e) (((p) = ns_get_efuns((s),(d))) && ((p)->e)) + + + +/***************************************************************************/ +/* module-global vars */ +/**********************/ + + + static long err_inhibit = 0; /* bits. avoid telling same error twice. */ static _ns_sess *sa = NULL; /* anchor for session list */ static _ns_hop *ha = NULL; /* anchor for hop list */ @@ -54,6 +76,20 @@ static _ns_hop *ha = NULL; /* anchor for hop list */ +/* ns_free + free a string (or whatever) */ + +void * +ns_free(char **x) +{ + if (!x || !*x) + return; + free(*x); + *x = NULL; +} + + + /* ns_new_hop. create and initialize a hop struct. lp local port. if 0: if otherwise matching hop exists, reuse that. otherwise, find the first free (as in, not used @@ -280,6 +316,7 @@ ns_new_sess(void) s->escape = NS_SCREEN_ESCAPE; /* default setup for the screen program */ s->literal = NS_SCREEN_LITERAL; s->dsbb = NS_SCREEN_DEFSBB; + s->delay = NS_INIT_DELAY; if (sa) { /* add to end of list */ _ns_sess *r = sa; while (r->next) @@ -341,28 +378,33 @@ ns_dst_sess(_ns_sess ** ss) int ns_screen_command(_ns_sess * sess, char *cmd) { + _ns_efuns *efuns; char *c; int ret = NS_SUCC; - if (!cmd || !*cmd) + if (!cmd || !*cmd) { return NS_FAIL; + } - if (sess->efuns->inp_text) { + if (NS_EFUN_EXISTS(efuns, sess, NULL, inp_text)) { if ((c = strdup(cmd))) { - { - char *p = c; /* replace default escape-char with that */ - while (*p) { /* actually used in this session */ - if (*p == NS_SCREEN_ESCAPE) - *p = sess->escape; - p++; + char *p; /* replace default escape-char with that */ + + for (p = c; *p; p++) { /* actually used in this session */ + if (*p == NS_SCREEN_ESCAPE) { + *p = sess->escape; } } - sess->efuns->inp_text(NULL, sess->fd, c); +#ifdef NS_DEBUG + ns_desc_string(c, "ns_screen_command: xlated string"); +#endif + efuns->inp_text(NULL, sess->fd, c); free(c); - } else + } else { + /* out of memory */ ret = NS_OOM; - } /* out of memory */ - else { + } + } else { ret = NS_EFUN_NOT_SET; fprintf(stderr, NS_PREFIX "ns_screen_command: sess->efuns->inp_text not set!\n"); } @@ -472,10 +514,12 @@ ns_upd_stat(_ns_sess * s) int ns_inp_dial(_ns_sess * s, char *prompt, int maxlen, char **retstr, int (*inp_tab) (void *, char *, size_t, size_t)) { + _ns_efuns *efuns; char *c; int ret = NS_SUCC; - if (s->efuns->inp_dial) { - (void) s->efuns->inp_dial((void *) s, prompt, maxlen, retstr, inp_tab); + + if (NS_EFUN_EXISTS(efuns, s, NULL, inp_dial)) { + (void) efuns->inp_dial((void *) s, prompt, maxlen, retstr, inp_tab); } else { ret = NS_EFUN_NOT_SET; fprintf(stderr, NS_PREFIX "ns_screen_command: sess->efuns->inp_dial not set!\n"); @@ -499,8 +543,10 @@ ns_inp_dial(_ns_sess * s, char *prompt, int maxlen, char **retstr, int (*inp_tab int ns_sess_init(_ns_sess * sess) { - if ((sess->backend == NS_MODE_NEGOTIATE) || (sess->backend == NS_MODE_SCREEN)) - return ns_parse_screenrc(sess); + if ((sess->backend == NS_MODE_NEGOTIATE) || (sess->backend == NS_MODE_SCREEN)) { + (void) ns_parse_screenrc(sess, sess->sysrc, NS_ESC_SYSSCREENRC); + return ns_parse_screenrc(sess, sess->home, NS_ESC_SCREENRC); + } return NS_SUCC; } @@ -579,11 +625,47 @@ ns_parse_hop(_ns_sess * s, char *h) +/* ns_desc_string + c the string + doc context-info + !stdout the string, in human-readable form */ + +void +ns_desc_string(char *c, char *doc) +{ + char *p = c; + + if (doc) + fprintf(stderr, NS_PREFIX "%s: ", doc); + + if (!c) { + fputs("NULL\n", stderr); + return; + } else if (!*c) { + fputs("empty\n", stderr); + return; + } + + while (*p) { + if (*p < ' ') + fprintf(stderr, "^%c", *p + 'A' - 1); + else + fputc(*p, stderr); + p++; + } + + fputs("\n", stderr); + + return; +} + + + /* ns_desc_hop print basic info about a hop (tunnel, firewall). mostly for debugging. hop: a hop struct as generated by (eg) ns_attach_by_URL() doc: info about the context - ! stdout: info about the hop */ + ! stderr: info about the hop */ void ns_desc_hop(_ns_hop * h, char *doc) @@ -607,13 +689,14 @@ ns_desc_hop(_ns_hop * h, char *doc) print basic info about a session. mostly for debugging. sess: a session struct as generated by (eg) ns_attach_by_URL() doc: info about the context - ! stdout: info about the session */ + ! stderr: info about the session */ void ns_desc_sess(_ns_sess * sess, char *doc) { if (!sess) { fprintf(stderr, NS_PREFIX "%s: ns_desc_sess called with broken pointer!\n", doc); + fflush(stderr); return; } if (sess->where == NS_LCL) @@ -627,8 +710,12 @@ ns_desc_sess(_ns_sess * sess, char *doc) fprintf(stderr, "%c%s\n", sess->where == NS_LCL ? ' ' : '/', sess->rsrc); if (sess->hop) ns_desc_hop(sess->hop, NULL); + if (sess->sysrc) + fprintf(stderr, NS_PREFIX "info: searching for sysrc in %s\n", sess->sysrc); if (sess->home) - fprintf(stderr, NS_PREFIX "info: searching for rc in %s\n", sess->home); + fprintf(stderr, NS_PREFIX "info: searching for usrrc in %s\n", sess->home); + fprintf(stderr, NS_PREFIX "info: escapes set to ^%c-%c\n", sess->escape + 'A' - 1, sess->literal); + fflush(stderr); } @@ -716,6 +803,64 @@ ns_run(_ns_efuns * efuns, char *cmd) +/* create a call line. used in ns_attach_ssh/lcl + tmpl the template. should contain one %s + dflt the default value + opt the user-supplied value (or NULL) + <- a new malloc'd string (or NULL) */ + +char * +ns_make_call_el(char *tmpl, char *dflt, char *opt) +{ + size_t l, r; + char *p; + + if (tmpl && dflt && *tmpl && strstr(tmpl, "%s")) { + l = strlen(tmpl) + (opt ? strlen(opt) : strlen(dflt)) - 1L; + if ((p = malloc(l))) { + r = snprintf(p, l, tmpl, opt ? opt : dflt); + if ((r >= 0) && (r < l)) { + return p; + } + free(p); + } + } + return NULL; +} + + + +char * +ns_make_call(_ns_sess * sess) +{ + char *call, *tmp = NULL, *screen = NULL, *scream = NULL, *screem = NULL; + + /* unless decidedly in other mode... */ + if (sess->backend != NS_MODE_SCREEN) + tmp = scream = ns_make_call_el(NS_SCREAM_CALL, NS_SCREAM_OPTS, sess->rsrc); + if (sess->backend != NS_MODE_SCREAM) + tmp = screen = ns_make_call_el(NS_SCREEN_CALL, NS_SCREEN_OPTS, sess->rsrc); + if (sess->backend == NS_MODE_NEGOTIATE) { + size_t r, l = strlen(NS_SCREEM_CALL) + strlen(scream) + strlen(screen) - 3; + if ((screem = malloc(l))) { + r = snprintf(screem, l, NS_SCREEM_CALL, scream, screen); +#ifdef NS_PARANOID + if ((r < 0) || (r > l)) { + ns_free(&screem); + } +#endif + } + tmp = screem; + } + call = ns_make_call_el(NS_WRAP_CALL, tmp, NULL); + ns_free(&screen); + ns_free(&scream); + ns_free(&screem); + return call; +} + + + /* attach a local session (using screen/scream) sp the session <- NS_FAIL, or the result of ns_run() */ @@ -724,28 +869,37 @@ int ns_attach_lcl(_ns_sess ** sp) { _ns_sess *sess; -#define MAXCMD 512 - char cmd[MAXCMD + 1]; - int ret; + char *call; + int ret = -1; if (!sp || !*sp) - return NS_FAIL; + return ret; + sess = *sp; - ret = snprintf(cmd, MAXCMD, "%s %s", NS_SCREEN_CALL, sess->rsrc ? sess->rsrc : NS_SCREEN_OPTS); - return (ret < 0 || ret > MAXCMD) ? NS_FAIL : ns_run(sess->efuns, cmd); + + if (call = ns_make_call(sess)) { + char *c2 = ns_make_call_el("/bin/sh -c \"%s\"", call, NULL); + ns_free(&call); + if (c2) { + ret = ns_run(sess->efuns, c2); + ns_free(&c2); + } + } + return ret; } /* attach a remote session (using screen/scream via ssh) sp the session - <- NS_FAIL, or the result of ns_run() */ + <- -1, or the result of ns_run() */ int ns_attach_ssh(_ns_sess ** sp) { _ns_sess *sess; - char cmd[MAXCMD + 1]; + char cmd[NS_MAXCMD + 1]; + char *call; int ret; if (!sp || !*sp) @@ -753,23 +907,31 @@ ns_attach_ssh(_ns_sess ** sp) sess = *sp; + call = ns_make_call(sess); + if (sess->hop) { if (sess->hop->established == NS_HOP_DOWN) { /* the nightmare foe */ - ret = snprintf(cmd, MAXCMD, "%s %s -p %d -L %d:%s:%d %s@%s", + ret = snprintf(cmd, NS_MAXCMD, "%s %s -p %d -L %d:%s:%d %s@%s", NS_SSH_CALL, NS_SSH_TUNNEL_OPTS, - sess->hop->fwport, sess->hop->localport, sess->host, sess->port, sess->user, sess->hop->fw, NS_SCREEM_CALL); - if (ret < 0 || ret > MAXCMD) + sess->hop->fwport, sess->hop->localport, sess->host, sess->port, sess->user, sess->hop->fw); + if (ret < 0 || ret > NS_MAXCMD) return NS_FAIL; ns_run(sess->efuns, cmd); sleep(sess->hop->delay); } - ret = snprintf(cmd, MAXCMD, "%s %s -p %d %s@localhost %s", - NS_SSH_CALL, NS_SSH_OPTS, sess->hop->localport, sess->user, NS_SCREEM_CALL); + ret = snprintf(cmd, NS_MAXCMD, "%s %s -p %d %s@localhost \"%s -e^%c%c\"", + NS_SSH_CALL, NS_SSH_OPTS, sess->hop->localport, sess->user, call, sess->escape + 'A' - 1, sess->literal); } else { - ret = snprintf(cmd, MAXCMD, "%s %s -p %d %s@%s %s", NS_SSH_CALL, NS_SSH_OPTS, sess->port, sess->user, sess->host, NS_SCREEM_CALL); + ret = + snprintf(cmd, NS_MAXCMD, "%s %s -p %d %s@%s \"%s -e^%c%c\"", NS_SSH_CALL, NS_SSH_OPTS, sess->port, sess->user, sess->host, call, + sess->escape + 'A' - 1, sess->literal); } - - return (ret < 0 || ret > MAXCMD) ? NS_FAIL : ns_run(sess->efuns, cmd); + ns_free(&call); +#ifdef NS_DEBUG + fprintf(stderr, "\n\n>>%s\n>>%s\n\n", call, cmd); + fflush(stderr); +#endif + return (ret < 0 || ret > NS_MAXCMD) ? NS_FAIL : ns_run(sess->efuns, cmd); } @@ -801,6 +963,8 @@ ns_attach_by_sess(_ns_sess ** sp, int *err) ns_desc_sess(sess, "ns_attach_by_sess()"); #endif + (void) ns_sess_init(sess); + switch (sess->where) { case NS_LCL: sess->fd = ns_attach_lcl(&sess); @@ -817,10 +981,9 @@ ns_attach_by_sess(_ns_sess ** sp, int *err) } #ifdef NS_DEBUG - fprintf(stderr, NS_PREFIX "ns_attach_by_sess: screen session-fd is %d\n", sess->fd); + fprintf(stderr, NS_PREFIX "ns_attach_by_sess: screen session-fd is %d, ^%c-%c\n", sess->fd, sess->escape + 'A' - 1, sess->literal); #endif - (void) ns_sess_init(sess); return sess; fail: @@ -929,6 +1092,7 @@ ns_attach_by_URL(char *url, char *hop, _ns_efuns ** ef, int *err, void *xd) if ((x = ns_parse_esc(&r)) && (y = ns_parse_esc(&r))) { sess->escape = x; sess->literal = y; + sess->escdef = NS_ESC_CMDLINE; } } else if (*r == 'c') { /* alt screenrc */ char *rc, *rx; @@ -991,20 +1155,37 @@ ns_attach_by_URL(char *url, char *hop, _ns_efuns ** ef, int *err, void *xd) goto fail; } else if (pwe && strcmp(pwe->pw_name, sess->user)) { /* user!=current_user */ sess->where = NS_SU; - if (!(pwe = getpwnam(sess->user))) { + if (!(pwe = getpwnam(sess->user)) && !sess->host && !sess->port) { *err = NS_UNKNOWN_USER; goto fail; } } - if (getenv("SCREENRC")) { + if (getenv("SYSSCREENRC")) { /* $SYSSCREENRC */ + if (!(sess->sysrc = strdup(getenv("SCREENRC")))) + goto fail; + } else { + char *loc[] = { "/usr/local/etc/screenrc", /* official */ + "/etc/screenrc", /* actual (on SuSE) */ + "/usr/etc/screenrc", + "/opt/etc/screenrc" + }; + int n, nloc = sizeof(loc) / sizeof(char *); + for (n = 0; n < nloc; n++) + if (!access(loc[n], R_OK)) { + if (!(sess->sysrc = strdup(loc[n]))) + goto fail; + n = nloc; + } + } + + if (getenv("SCREENRC")) { /* $SCREENRC */ sess->home = strdup(getenv("SCREENRC")); - } else if (pwe && !sess->home) { + } else if (pwe && !sess->home) { /* ~/.screenrc */ if ((sess->home = malloc(strlen(pwe->pw_dir) + strlen(NS_SCREEN_RC) + 2))) sprintf(sess->home, "%s/%s", pwe->pw_dir, NS_SCREEN_RC); - else - goto fail; - } + } else + goto fail; if (!sess->host) { /* no host */ if (!(sess->host = strdup("localhost"))) @@ -1020,7 +1201,7 @@ ns_attach_by_URL(char *url, char *hop, _ns_efuns ** ef, int *err, void *xd) sess->backend = NS_MODE_NEGOTIATE; if (!sess->proto) { - if (!(sess->proto = strdup("scream"))) + if (!(sess->proto = strdup("screXX"))) goto fail; } else if (!strcmp(sess->proto, "screen")) sess->backend = NS_MODE_SCREEN; @@ -1061,7 +1242,9 @@ ns_attach_by_URL(char *url, char *hop, _ns_efuns ** ef, int *err, void *xd) int ns_detach(_ns_sess ** sess) { +#ifdef NS_DEBUG ns_desc_sess(*sess, "ns_detach"); +#endif (void) ns_dst_sess(sess); return NS_SUCC; } @@ -1181,6 +1364,15 @@ ns_register_tab(_ns_efuns * efuns, int (*inp_tab) (void *, char *[], int, char * +/* function that will do whatever while waiting */ +void +ns_register_fun(_ns_efuns * efuns, int (*inp_fun) (void *, int)) +{ + efuns->waitstate = inp_fun; +} + + + /* get callbacks. at least one of session and display must be non-NULL. s session, or NULL. if NULL, will be initialized from d->sess d display, or NULL. if NULL, will be initialized from s->curr. @@ -1208,20 +1400,6 @@ ns_get_efuns(_ns_sess * s, _ns_disp * d) -/* test if we have a valid callback for function-type "e". - !p a variable of the "_ns_efuns *" type. will contain a pointer to - an efun struct containing a function pointer to the requested function - if such a struct exists, or NULL, if it doesn't exist - s a variable of the "_ns_sess *" type, or NULL (see ns_get_efuns()) - d a variable of the "_nd_disp *" type, or NULL (see ns_get_efuns()) - e the name of an element of "_ns_efuns" - !<- conditional execution of next (compound-) statement (which would - normally be (p)->(e)(...), the call of the function e). - */ -#define NS_IF_EFUN_EXISTS(p,s,d,e) if(((p)=ns_get_efuns((s),(d)))&&((p)->e)) - - - /***************************************************************************/ /* display-handling */ /********************/ @@ -1282,10 +1460,8 @@ disp_fetch_or_make(_ns_sess * s, int n) d->sess = s; /* note session on display */ -#if 1 if (!d->sess->curr) /* note as current on session if first display */ d->sess->curr = d; -#endif return d; } @@ -1407,11 +1583,13 @@ ns_inp_tab(void *xd, char *b, size_t l, size_t m) "writelock", "xoff", "xon", "zombie" }; + _ns_efuns *efuns; _ns_sess *s = (_ns_sess *) xd; int nsc = sizeof(sc) / sizeof(char *); - if (s->efuns->inp_tab) - return s->efuns->inp_tab((void *) s, sc, nsc, b, l, m) < 0 ? NS_FAIL : NS_SUCC; + if (NS_EFUN_EXISTS(efuns, s, NULL, inp_tab)) { + return efuns->inp_tab((void *) s, sc, nsc, b, l, m) < 0 ? NS_FAIL : NS_SUCC; + } fprintf(stderr, NS_PREFIX "ns_screen_command: sess->efuns->inp_tab not set!\n"); return NS_EFUN_NOT_SET; @@ -1470,12 +1648,13 @@ ns_parse_esc(char **x) /* ns_parse_screen_cmd parse a command the user intends to send to the screen program, either via .screenrc or using ^A: - s the affected (current) session. s->current should be set. - p the command + s the affected (current) session. s->current should be set. + p the command + whence which parsing stage (screenrc, interactive, ...) <- error code */ int -ns_parse_screen_cmd(_ns_sess * s, char *p) +ns_parse_screen_cmd(_ns_sess * s, char *p, int whence) { char *p2; long v1 = -1; @@ -1492,21 +1671,33 @@ ns_parse_screen_cmd(_ns_sess * s, char *p) v1 = -1; } #define IS_CMD(b) (strncasecmp(p,b,strlen(b))==0) - if (!p2) + if (!p2) { fprintf(stderr, NS_PREFIX "screenrc: ignoring \"%s\" without an argument...\n", p); - else if (IS_CMD("defescape")) + /* must return success so it's fowarded to screen in interactive mode. + that way, the user can read the original reply instead of a fake + one from us. */ + return NS_SUCC; + } else if (IS_CMD("defescape")) fprintf(stderr, NS_PREFIX "screenrc: ignoring \"defescape\", did you mean \"escape\"?\n"); - else if (IS_CMD("defhstatus") || IS_CMD("hardstatus") || IS_CMD("echo") || - IS_CMD("colon") || IS_CMD("nethack") || - IS_CMD("info") || IS_CMD("time") || IS_CMD("title") || IS_CMD("wall") || - IS_CMD("lastmsg") || IS_CMD("msgwait") || IS_CMD("msgminwait")) + else if (IS_CMD("defhstatus") || IS_CMD("hardstatus") || IS_CMD("echo") || IS_CMD("colon") || IS_CMD("wall") || +#ifdef NS_PARANOID + IS_CMD("nethack") || +#endif + IS_CMD("info") || IS_CMD("time") || IS_CMD("title") || IS_CMD("lastmsg") || IS_CMD("msgwait") || IS_CMD("msgminwait")) { fprintf(stderr, NS_PREFIX "screenrc: ignoring \"%s\", not applicable...\n", p); - else if (IS_CMD("escape")) { + return NS_NOT_ALLOWED; + } else if (IS_CMD("escape")) { char x = 0, y = 0; if ((x = ns_parse_esc(&p2)) && (y = ns_parse_esc(&p2))) { - s->escape = x; - s->literal = y; - return NS_SUCC; + if (s->escdef == NS_ESC_CMDLINE) { + fprintf(stderr, NS_PREFIX "screenrc: ignoring \"escape\"; overridden on command-line...\n", x, y); + return NS_NOT_ALLOWED; + } else { + s->escape = x; + s->literal = y; + s->escdef = whence; + return NS_SUCC; + } } else fprintf(stderr, NS_PREFIX "screenrc: ignoring \"escape\" because of invalid arguments %o %o...\n", x, y); } else if (IS_CMD("defscrollback")) { @@ -1570,8 +1761,11 @@ ns_parse_screen_key(_ns_sess * s, char c) case NS_SCREEN_CMD: /* send command (statement) to screen server */ (void) ns_inp_dial((void *) s, "Enter a command to send to the \"screen\" program", 64, &i, ns_inp_tab); if (i) { - ret = ns_screen_xcommand(s, c, i); - (void) ns_parse_screen_cmd(s, i); + if ((ret = ns_parse_screen_cmd(s, i, NS_ESC_INTERACTIVE)) == NS_SUCC) { + ret = ns_screen_xcommand(s, c, i); + } else if (ret == NS_NOT_ALLOWED) { + menu_dial(NULL, "Sorry, David, I cannot allow that.", 0, NULL, NULL); + } free(i); } break; @@ -1600,24 +1794,72 @@ ns_parse_screen_key(_ns_sess * s, char c) -/* ns_parse_screenrc -- read the user's screenrc (if we can find it), - parse it (we need to know if she changes the escapes etc.), and - send it to the actually screen +/* ns_parse_screen_interactive + parse a whole string that may contain screen-escapes that should be + handled interactively (that should open dialog boxes etc.). + this will normally be called by menus, buttons etc. that want to send + input to the add without generating X events for the keystrokes (real + keystrokes do not come through here; the keyboard-handler should call + ns_parse_screen_key() directly when it sees the session's escape-char). s the session in question + c the string to parse <- error code */ int -ns_parse_screenrc(_ns_sess * s) +ns_parse_screen_interactive(_ns_sess * sess, char *c) +{ + char *s, *p, *o; + + if (!c || !*c) + return NS_FAIL; +#ifdef NS_PARANOID + if (!(s = o = strdup(c))) + return NS_FAIL; +#else + s = c; +#endif + + p = s; + + while ((p = strchr(s, NS_SCREEN_ESCAPE))) { + *p = '\0'; + (void) ns_screen_command(sess, s); + *p = NS_SCREEN_ESCAPE; + if (*(++p)) + ns_parse_screen_key(sess, *(p++)); + s = p; + } + (void) ns_screen_command(sess, s); + +#ifdef NS_PARANOID + free(o); +#endif + + return NS_SUCC; +} + + + +/* ns_parse_screenrc -- read the user's screenrc (if we can find it), + parse it (we need to know if she changes the escapes etc.), and + send it to the actually screen + s the session + fn name of the file in question + whence which screenrc are we in? + <- error code */ + +int +ns_parse_screenrc(_ns_sess * s, char *fn, int whence) { int fd = -1; char *rc = NULL; char _e = '\0', _l = '\0', *esc = NULL; - if (s->home) { + if (fn) { struct stat st; ssize_t rd = 0; - if ((fd = open(s->home, 0)) >= 0) { + if ((fd = open(fn, 0)) >= 0) { if (!fstat(fd, &st)) { if ((rc = malloc(st.st_size + 1))) { char *p; @@ -1655,7 +1897,7 @@ ns_parse_screenrc(_ns_sess * s) } if (strlen(p)) /* any commands in line? */ - ns_parse_screen_cmd(s, p); + ns_parse_screen_cmd(s, p, whence); p = n; /* done, next line */ } free(rc); @@ -1705,8 +1947,9 @@ ns_parse_screen_msg(_ns_sess * screen, char *p) type = (strlen(p) > 1) ? NS_SCREEN_STATUS : NS_SCREEN_ST_CLR; if (type == NS_SCREEN_ST_CLR) { - NS_IF_EFUN_EXISTS(efuns, screen, NULL, err_msg) + if (NS_EFUN_EXISTS(efuns, screen, NULL, err_msg)) { ret = efuns->err_msg(NULL, type, ""); + } } /* a screen display can disappear because the program in it dies, or because we explicitly ask screen to kill the display. in the latter @@ -1723,15 +1966,19 @@ ns_parse_screen_msg(_ns_sess * screen, char *p) p = NULL; } else if (!strcmp(p, "New screen...") || !strncmp(p, "msgwait", strlen("msgwait")) || !strncmp(p, "msgminwait", strlen("msgminwait"))) p = NULL; +#ifndef NS_PARANOID + /* FIXME. */ else if (sscanf(p, NS_SCREEN_VERSION, &p3, &ma, &mi, &mu, &p2, &d) == 6) { if (!strcmp("en", p3)) screen->backend = NS_MODE_SCREEN; else if (!strcmp("am", p3)) screen->backend = NS_MODE_SCREAM; -#ifdef NS_DEBUG +# ifdef NS_DEBUG fprintf(stderr, NS_PREFIX "ns_parse_screen_msg: scre%s %d.%2d.%2d %s a/o %s\n", p3, ma, mi, mu, p2, d); +# endif + } #endif - } else if (!strcmp(p, NS_SCREEN_NO_DEBUG)) + else if (!strcmp(p, NS_SCREEN_NO_DEBUG)) p = "debug info was not compiled into \"screen\"..."; else if (!strncmp(p, NS_SCREEN_DK_CMD, strlen(NS_SCREEN_DK_CMD))) { p[strlen(p) - 1] = '\0'; @@ -1739,8 +1986,9 @@ ns_parse_screen_msg(_ns_sess * screen, char *p) p = "unknown screen statement ignored"; } if (p) { /* status. send to status-line or dialog or whatever */ - NS_IF_EFUN_EXISTS(efuns, screen, NULL, err_msg) + if (NS_EFUN_EXISTS(efuns, screen, NULL, err_msg)) { ret = efuns->err_msg(NULL, type, p); + } } return ret; } @@ -1788,7 +2036,7 @@ ns_parse_screen(_ns_sess * screen, int force, int width, char *p) if (!screen || !p || !width) return NS_FAIL; - if (!force) + if (!force && screen->timestamp) return NS_SUCC; if (p = strdup(p)) { @@ -1803,17 +2051,26 @@ ns_parse_screen(_ns_sess * screen, int force, int width, char *p) fprintf(stderr, NS_PREFIX "parse_screen: screen sends ::%s::\n", p); #endif -#ifdef NS_PARANOID_ if (strlen(p) < 2) { /* special case: display 0 */ disp = screen->dsps; /* might not get a status-line in d0! */ if (disp && !(disp->flags & NS_SCREAM_CURR)) { /* flags need updating */ disp->flags |= NS_SCREAM_CURR; /* set flag to avoid calling inp_text */ ret = ns_upd_stat(screen); - } /* more than once */ + } /* more than once */ + else if (!screen->timestamp) { + screen->timestamp = time(NULL); + if (screen->delay > 0) { + if (NS_EFUN_EXISTS(efuns, screen, NULL, waitstate)) { + ret = efuns->waitstate(NULL, screen->delay * 1000); + } else { + sleep(screen->delay); + } + } + (void) ns_screen_command(screen, NS_SCREEN_INIT); + } free(p); return ret; } -#endif p3 = p; while (isspace(*p3)) /* skip left padding */ @@ -1876,8 +2133,9 @@ ns_parse_screen(_ns_sess * screen, int force, int width, char *p) fprintf(stderr, NS_PREFIX "parse_screen: out of memory in new_display(%d)\n", n); ret = NS_FAIL; } else { - NS_IF_EFUN_EXISTS(efuns, screen, NULL, ins_disp) + if (NS_EFUN_EXISTS(efuns, screen, NULL, ins_disp)) { ret = efuns->ins_disp(screen->userdef, pd[r].real - 1, disp->name); + } } } else if ((tmp = strcmp(disp->name, pd[r].name)) || /* upd display */ (disp->flags != pd[r].flags)) { @@ -1891,8 +2149,9 @@ ns_parse_screen(_ns_sess * screen, int force, int width, char *p) if (pd[r].flags & NS_SCREAM_CURR) disp->sess->curr = disp; disp->flags = pd[r].flags & NS_SCREAM_MASK; - NS_IF_EFUN_EXISTS(efuns, screen, NULL, upd_disp) + if (NS_EFUN_EXISTS(efuns, screen, NULL, upd_disp)) { ret = efuns->upd_disp(screen->userdef, r, disp->flags, disp->name); + } } /* remove any displays from list that have disappeared @@ -1904,8 +2163,9 @@ ns_parse_screen(_ns_sess * screen, int force, int width, char *p) fprintf(stderr, NS_PREFIX "parse_screen: remove expired middle %d \"%s\"...\n", d3->index, d3->name); #endif d4 = d3->prvs; - NS_IF_EFUN_EXISTS(efuns, screen, NULL, del_disp) + if (NS_EFUN_EXISTS(efuns, screen, NULL, del_disp)) { ret = efuns->del_disp(screen->userdef, disp_get_real_by_screen(screen, d3->index)); + } disp_kill(d3); d3 = d4; } @@ -1945,8 +2205,9 @@ ns_parse_screen(_ns_sess * screen, int force, int width, char *p) if (d2->sess->curr == d2) d2->sess->curr = d3; disp = disp->next; - NS_IF_EFUN_EXISTS(efuns, screen, NULL, del_disp) + if (NS_EFUN_EXISTS(efuns, screen, NULL, del_disp)) { ret = efuns->del_disp(screen->userdef, disp_get_real_by_screen(screen, d2->index)); + } disp_kill(d2); } d3->next = NULL; @@ -1963,26 +2224,12 @@ ns_parse_screen(_ns_sess * screen, int force, int width, char *p) we could send it before entering this function for the first time, but that would break if escapes or screenrc were set from the command-line. don't ask. */ -#ifdef NS_DEBUG - if (!screen) - fprintf(stderr, NS_PREFIX "parse_screen: session went away!?\n\n CONDITION RED!\n CONDITION RED!\n DANGER WILL ROBINSON!!!\n\n"); - else -#endif - { - if (!screen->timestamp) { - screen->timestamp = time(NULL); -#ifdef NS_DEBUG - fprintf(stderr, NS_PREFIX "parse_screen: sending NS_SCREEN_INIT with prefix %d...\n", screen->escape); -#endif - ret = ns_screen_command(screen, NS_SCREEN_INIT); - } #if (NS_SCREEN_UPD_FREQ>0) - else if ((t2 - screen->timestamp) > NS_SCREEN_UPD_FREQ) { - (void) ns_upd_stat(screen); - screen->timestamp = t2; - } -#endif + if ((t2 - screen->timestamp) > NS_SCREEN_UPD_FREQ) { + (void) ns_upd_stat(screen); + screen->timestamp = t2; } +#endif return ret; } diff --git a/src/menus.c b/src/menus.c index 641e7d3..a559ef7 100644 --- a/src/menus.c +++ b/src/menus.c @@ -43,6 +43,9 @@ static const char cvs_ident[] = "$Id$"; #include "script.h" #include "term.h" #include "windows.h" +#ifdef ESCREEN +# include "screamcfg.h" +#endif menulist_t *menu_list = NULL; #ifndef ESCREEN @@ -721,7 +724,7 @@ menuitem_delete(menuitem_t *item) if (item->icon) { free_simage(item->icon); } - if (item->type == MENUITEM_STRING || item->type == MENUITEM_ECHO) { + if (item->type == MENUITEM_STRING || item->type == MENUITEM_LITERAL || item->type == MENUITEM_ECHO) { FREE(item->action.string); } else if (item->type == MENUITEM_SCRIPT) { FREE(item->action.script); @@ -779,9 +782,11 @@ menuitem_set_action(menuitem_t *item, unsigned char type, char *action) break; case MENUITEM_STRING: case MENUITEM_ECHO: + case MENUITEM_LITERAL: item->action.string = (char *) MALLOC(strlen(action) + 2); strcpy(item->action.string, action); - parse_escaped_string(item->action.string); + if (type != MENUITEM_LITERAL) + parse_escaped_string(item->action.string); break; default: break; @@ -1219,20 +1224,14 @@ menu_action(menuitem_t *item) case MENUITEM_ECHO: #ifdef ESCREEN if (TermWin.screen_mode && TermWin.screen) { /* translate escapes */ -# ifdef NS_DEBUG - { - char *p = item->action.string; - fprintf(stderr, NS_PREFIX "::menu_action: "); - while (*p) { - if (*p < ' ') - fprintf(stderr, "^%c", *p - 1 + 'A'); - else - fprintf(stderr, "%c", *p); - p++; - } - fputs("\n", stderr); - } -# endif + ns_parse_screen_interactive(TermWin.screen, item->action.string); + } else +#endif + tt_write((unsigned char *) item->action.string, strlen(item->action.string)); + break; + case MENUITEM_LITERAL: +#ifdef ESCREEN + if (TermWin.screen_mode && TermWin.screen) { /* translate escapes */ (void) ns_screen_command(TermWin.screen, item->action.string); } else #endif diff --git a/src/menus.h b/src/menus.h index 5f461ee..e628888 100644 --- a/src/menus.h +++ b/src/menus.h @@ -35,6 +35,7 @@ #define MENUITEM_ECHO (1UL << 3) #define MENUITEM_SCRIPT (1UL << 4) #define MENUITEM_ALERT (1UL << 5) +#define MENUITEM_LITERAL (1UL << 6) #define MENU_STATE_IS_MAPPED (1UL << 0) #define MENU_STATE_IS_CURRENT (1UL << 1) diff --git a/src/options.c b/src/options.c index f3ed570..3702292 100644 --- a/src/options.c +++ b/src/options.c @@ -139,6 +139,7 @@ char *rs_config_file = NULL; #ifdef ESCREEN char *rs_url = NULL; char *rs_hop = NULL; +int rs_delay = -1; #endif unsigned int rs_line_space = 0; unsigned int rs_meta_mod = 0, rs_alt_mod = 0, rs_numlock_mod = 0; @@ -168,6 +169,7 @@ static const struct { #ifdef ESCREEN OPT_STR('U', "URL", "an URL pointing at a screen-session to pick up", &rs_url), OPT_STR('Z', "[lclport:]fw[:fwport]", "the destination machine -U can only be seen by the firewall fw. tunnel.", &rs_hop), + OPT_INT('z', "delay", "initial delay in seconds", &rs_delay), #endif #if DEBUG <= 0 OPT_ILONG("debug", "level of debugging information to show (support not compiled in)", &DEBUG_LEVEL), @@ -1566,10 +1568,12 @@ parse_toggles(char *buff, void *state) } else if (!BEG_STRCASECMP(buff, "buttonbar")) { if (bool_val) { - FOREACH_BUTTONBAR(bbar_set_visible(bbar, 1);); + FOREACH_BUTTONBAR(bbar_set_visible(bbar, 1); + ); rs_buttonbars = 1; /* Reset for future use. */ } else { - FOREACH_BUTTONBAR(bbar_set_visible(bbar, 0);); + FOREACH_BUTTONBAR(bbar_set_visible(bbar, 0); + ); rs_buttonbars = 1; /* Reset for future use. */ } @@ -3055,9 +3059,11 @@ post_parse(void) specified. If specified, it will either become 3 (on) or 0 (off). */ if (rs_buttonbars != 1) { if (rs_buttonbars) { - FOREACH_BUTTONBAR(bbar_set_visible(bbar, 1);); + FOREACH_BUTTONBAR(bbar_set_visible(bbar, 1); + ); } else { - FOREACH_BUTTONBAR(bbar_set_visible(bbar, 0);); + FOREACH_BUTTONBAR(bbar_set_visible(bbar, 0); + ); } rs_buttonbars = 1; /* Reset for future use. */ } diff --git a/src/options.h b/src/options.h index 1d01a5c..9653a1d 100644 --- a/src/options.h +++ b/src/options.h @@ -137,6 +137,7 @@ extern char *rs_config_file; #ifdef ESCREEN extern char *rs_url; extern char *rs_hop; +extern int rs_delay; #endif extern unsigned int rs_line_space; extern unsigned int rs_meta_mod, rs_alt_mod, rs_numlock_mod; diff --git a/src/pixmap.c b/src/pixmap.c index 9128ab3..353e748 100644 --- a/src/pixmap.c +++ b/src/pixmap.c @@ -614,8 +614,6 @@ check_image_ipc(unsigned char reset) print_error("ImageClass \"%s\" is not defined in Enlightenment. Disallowing \"auto\" mode for this image.\n", iclass); image_mode_fallback(i); } else if (strstr(reply, "Error")) { - print_error("Looks like this version of Enlightenment doesn't support the IPC " - "commands I need. Disallowing \"auto\" mode for all images.\n"); /* *INDENT-OFF* */ FOREACH_IMAGE( if (image_mode_is(idx, MODE_AUTO)) { @@ -630,6 +628,8 @@ check_image_ipc(unsigned char reset) } ); /* *INDENT-ON* */ + print_error("Looks like this version of Enlightenment doesn't support the IPC " + "commands I need. Disallowing \"auto\" mode for all images.\n"); FREE(reply); checked = 2; return 0; @@ -678,8 +678,8 @@ create_trans_pixmap(simage_t *simg, unsigned char which, Drawable d, int x, int XSetFillStyle(Xdisplay, gc, FillTiled); XFillRectangle(Xdisplay, p, gc, 0, 0, width, height); } else { - D_PIXMAP(("Copying %hux%hu rectangle at %d, %d from %ux%u desktop pixmap 0x%08x onto p.\n", width, height, x, y, pw, ph, - desktop_pixmap)); + D_PIXMAP(("Copying %hux%hu rectangle at %d, %d from %ux%u desktop pixmap 0x%08x onto p.\n", width, height, x, y, pw, + ph, desktop_pixmap)); XCopyArea(Xdisplay, desktop_pixmap, p, gc, x, y, width, height, 0, 0); } if ((which != image_bg || (image_toggles & IMOPT_ITRANS) || images[image_bg].current != images[image_bg].norm) @@ -687,8 +687,8 @@ create_trans_pixmap(simage_t *simg, unsigned char which, Drawable d, int x, int colormod_trans(p, simg->iml, gc, width, height); } if (simg->iml->bevel != NULL) { - D_PIXMAP(("Beveling pixmap 0x%08x with edges %d, %d, %d, %d\n", p, simg->iml->bevel->edges->left, simg->iml->bevel->edges->top, - simg->iml->bevel->edges->right, simg->iml->bevel->edges->bottom)); + D_PIXMAP(("Beveling pixmap 0x%08x with edges %d, %d, %d, %d\n", p, simg->iml->bevel->edges->left, + simg->iml->bevel->edges->top, simg->iml->bevel->edges->right, simg->iml->bevel->edges->bottom)); bevel_pixmap(p, width, height, simg->iml->bevel->edges, simg->iml->bevel->up); } } @@ -706,12 +706,10 @@ create_viewport_pixmap(simage_t *simg, Drawable d, int x, int y, unsigned short Pixmap p = None, mask = None; GC gc; Screen *scr; - D_PIXMAP(("create_viewport_pixmap(%8p, 0x%08x, %d, %d, %hu, %hu) called.\n", simg, d, x, y, width, height)); scr = ScreenOfDisplay(Xdisplay, Xscreen); if (!scr) return None; - if (desktop_window == None) { get_desktop_window(); if (desktop_window == None) { @@ -721,7 +719,6 @@ create_viewport_pixmap(simage_t *simg, Drawable d, int x, int y, unsigned short } if (viewport_pixmap == None) { imlib_t *tmp_iml = images[image_bg].current->iml; - imlib_context_set_image(tmp_iml->im); imlib_context_set_drawable(d); imlib_image_set_has_alpha(0); @@ -736,7 +733,6 @@ create_viewport_pixmap(simage_t *simg, Drawable d, int x, int y, unsigned short imlib_image_set_border(&bord_none); } imlib_context_set_color_modifier((tmp_iml->mod && tmp_iml->mod->imlib_mod) ? tmp_iml->mod->imlib_mod : NULL); - if ((images[image_bg].current->pmap->w > 0) || (images[image_bg].current->pmap->op & OP_SCALE)) { D_PIXMAP(("Scaling image to %dx%d\n", scr->width, scr->height)); imlib_render_pixmaps_for_whole_image_at_size(&viewport_pixmap, &mask, scr->width, scr->height); @@ -786,23 +782,19 @@ create_viewport_pixmap(simage_t *simg, Drawable d, int x, int y, unsigned short } void -paste_simage(simage_t *simg, unsigned char which, Window win, Drawable d, unsigned short x, unsigned short y, unsigned short w, - unsigned short h) +paste_simage(simage_t *simg, unsigned char which, Window win, Drawable d, unsigned short x, unsigned short y, + unsigned short w, unsigned short h) { Pixmap pmap = None, mask = None; GC gc; - ASSERT(simg != NULL); REQUIRE(d != None); - - D_PIXMAP(("paste_simage(%8p, %s, 0x%08x, 0x%08x, %hd, %hd, %hd, %hd) called.\n", simg, get_image_type(which), (int) win, (int) d, x, y, - w, h)); - + D_PIXMAP(("paste_simage(%8p, %s, 0x%08x, 0x%08x, %hd, %hd, %hd, %hd) called.\n", simg, get_image_type(which), + (int) win, (int) d, x, y, w, h)); if (which != image_max) { if (image_mode_is(which, MODE_AUTO) && image_mode_is(which, ALLOW_AUTO)) { char buff[255], *reply; const char *iclass, *state; - check_image_ipc(0); if (image_mode_is(which, MODE_AUTO)) { iclass = get_iclass_name(which); @@ -814,7 +806,6 @@ paste_simage(simage_t *simg, unsigned char which, Window win, Drawable d, unsign state = "normal"; } D_PIXMAP((" -> iclass == \"%s\", state == \"%s\"\n", NONULL(iclass), NONULL(state))); - if (iclass) { snprintf(buff, sizeof(buff), "imageclass %s apply_copy 0x%x %s %hd %hd", iclass, (int) d, state, w, h); reply = enl_send_and_wait(buff); @@ -848,7 +839,6 @@ paste_simage(simage_t *simg, unsigned char which, Window win, Drawable d, unsign } } else if (image_mode_is(which, MODE_TRANS) && image_mode_is(which, ALLOW_TRANS)) { Pixmap p; - gc = LIBAST_X_CREATE_GC(0, NULL); p = create_trans_pixmap(simg, which, win, x, y, w, h); if (p != None) { @@ -860,7 +850,6 @@ paste_simage(simage_t *simg, unsigned char which, Window win, Drawable d, unsign LIBAST_X_FREE_GC(gc); } else if (image_mode_is(which, MODE_VIEWPORT) && image_mode_is(which, ALLOW_VIEWPORT)) { Pixmap p; - gc = LIBAST_X_CREATE_GC(0, NULL); p = create_viewport_pixmap(simg, win, x, y, w, h); if (simg->iml->bevel != NULL) { @@ -884,7 +873,6 @@ paste_simage(simage_t *simg, unsigned char which, Window win, Drawable d, unsign imlib_image_set_border(&bord_none); } imlib_context_set_color_modifier((simg->iml->mod && simg->iml->mod->imlib_mod) ? simg->iml->mod->imlib_mod : NULL); - if (w == imlib_image_get_width() && h == imlib_image_get_height()) { imlib_render_pixmaps_for_whole_image(&pmap, &mask); } else { @@ -962,16 +950,13 @@ copy_buffer_pixmap(unsigned char mode, unsigned long fill, unsigned short width, { GC gc; XGCValues gcvalue; - ASSERT(buffer_pixmap == None); buffer_pixmap = LIBAST_X_CREATE_PIXMAP(width, height); gcvalue.foreground = (Pixel) fill; gc = LIBAST_X_CREATE_GC(GCForeground, &gcvalue); XSetGraphicsExposures(Xdisplay, gc, False); - if (mode == MODE_SOLID) { simage_t *simg; - simg = images[image_bg].current; if (simg->pmap->pixmap) { LIBAST_X_FREE_PIXMAP(simg->pmap->pixmap); @@ -998,20 +983,16 @@ render_simage(simage_t *simg, Window win, unsigned short width, unsigned short h unsigned short rendered = 0; unsigned short xscaled = 0, yscaled = 0; #endif - scr = ScreenOfDisplay(Xdisplay, Xscreen); if (!scr) return; - ASSERT(simg != NULL); ASSERT(simg->iml != NULL); ASSERT(simg->pmap != NULL); REQUIRE(win != None); - - D_PIXMAP(("Rendering simg->iml->im %8p (%s) at %hux%hu onto window 0x%08x\n", simg->iml->im, get_image_type(which), width, height, - win)); + D_PIXMAP(("Rendering simg->iml->im %8p (%s) at %hux%hu onto window 0x%08x\n", simg->iml->im, get_image_type(which), + width, height, win)); D_PIXMAP(("Image mode is 0x%02x\n", images[which].mode)); - #ifdef PIXMAP_SUPPORT if ((which == image_bg) && image_mode_is(image_bg, MODE_VIEWPORT)) { width = scr->width; @@ -1020,11 +1001,9 @@ render_simage(simage_t *simg, Window win, unsigned short width, unsigned short h #endif if (!(width) || !(height)) return; - gcvalue.foreground = gcvalue.background = PixColors[bgColor]; gc = LIBAST_X_CREATE_GC(GCForeground | GCBackground, &gcvalue); pixmap = simg->pmap->pixmap; /* Save this for later */ - if ((which == image_bg) && (buffer_pixmap != None)) { LIBAST_X_FREE_PIXMAP(buffer_pixmap); buffer_pixmap = None; @@ -1033,7 +1012,6 @@ render_simage(simage_t *simg, Window win, unsigned short width, unsigned short h if ((images[which].mode & MODE_AUTO) && (images[which].mode & ALLOW_AUTO)) { char buff[255]; const char *iclass, *state; - check_image_ipc(0); if (image_mode_is(which, MODE_AUTO)) { iclass = get_iclass_name(which); @@ -1047,7 +1025,6 @@ render_simage(simage_t *simg, Window win, unsigned short width, unsigned short h if (iclass) { if (renderop & RENDER_FORCE_PIXMAP) { char *reply; - snprintf(buff, sizeof(buff), "imageclass %s apply_copy 0x%x %s %hd %hd", iclass, (int) win, state, width, height); reply = enl_send_and_wait(buff); if (strstr(reply, "Error")) { @@ -1057,7 +1034,6 @@ render_simage(simage_t *simg, Window win, unsigned short width, unsigned short h FREE(reply); } else { Pixmap pmap, mask; - pmap = (Pixmap) strtoul(reply, (char **) NULL, 0); mask = (Pixmap) strtoul(get_pword(2, reply), (char **) NULL, 0); FREE(reply); @@ -1118,7 +1094,6 @@ render_simage(simage_t *simg, Window win, unsigned short width, unsigned short h } } else if (image_mode_is(which, MODE_VIEWPORT) && image_mode_is(which, ALLOW_VIEWPORT)) { Pixmap p; - D_PIXMAP(("Viewport mode enabled. viewport_pixmap == 0x%08x and simg->pmap->pixmap == 0x%08x\n", viewport_pixmap, simg->pmap->pixmap)); p = create_viewport_pixmap(simg, win, 0, 0, width, height); @@ -1151,7 +1126,6 @@ render_simage(simage_t *simg, Window win, unsigned short width, unsigned short h int h = simg->pmap->h; int x = simg->pmap->x; int y = simg->pmap->y; - imlib_context_set_image(simg->iml->im); imlib_context_set_drawable(win); imlib_context_set_anti_alias(1); @@ -1160,10 +1134,8 @@ render_simage(simage_t *simg, Window win, unsigned short width, unsigned short h xsize = imlib_image_get_width(); ysize = imlib_image_get_height(); D_PIXMAP(("w == %d, h == %d, x == %d, y == %d, xsize == %d, ysize == %d\n", w, h, x, y, xsize, ysize)); - if ((simg->pmap->op & OP_PROPSCALE) && w && h) { double x_ratio, y_ratio; - x_ratio = ((double) width) / ((double) xsize); y_ratio = ((double) height) / ((double) ysize); if (x_ratio > 1) { @@ -1195,7 +1167,6 @@ render_simage(simage_t *simg, Window win, unsigned short width, unsigned short h xpos = (short) ((width - xscaled) * ((float) x / 100.0)); ypos = (short) ((height - yscaled) * ((float) y / 100.0)); D_PIXMAP(("Calculated scaled size as %hux%hu with origin at (%hd, %hd)\n", xscaled, yscaled, xpos, ypos)); - if (simg->iml->border) { D_PIXMAP(("Setting image border: { left [%d], right [%d], top [%d], bottom [%d] }\n", simg->iml->border->left, simg->iml->border->right, simg->iml->border->top, simg->iml->border->bottom)); @@ -1204,7 +1175,6 @@ render_simage(simage_t *simg, Window win, unsigned short width, unsigned short h imlib_image_set_border(&bord_none); } imlib_context_set_color_modifier((simg->iml->mod && simg->iml->mod->imlib_mod) ? simg->iml->mod->imlib_mod : NULL); - D_PIXMAP(("Rendering image simg->iml->im [%8p] to %hdx%hd pixmap\n", simg->iml->im, xscaled, yscaled)); imlib_render_pixmaps_for_whole_image_at_size(&simg->pmap->pixmap, &simg->pmap->mask, xscaled, yscaled); rendered = 1; @@ -1215,10 +1185,8 @@ render_simage(simage_t *simg, Window win, unsigned short width, unsigned short h } if (xscaled != width || yscaled != height || xpos != 0 || ypos != 0) { unsigned char single; - /* This tells us if we have a single, non-tiled image which does not entirely fill the window */ single = ((xscaled < width || yscaled < height) && !(simg->pmap->op & OP_TILE)) ? 1 : 0; - pixmap = simg->pmap->pixmap; simg->pmap->pixmap = LIBAST_X_CREATE_PIXMAP(width, height); if (single) { @@ -1307,7 +1275,6 @@ search_path(const char *pathlist, const char *file) const char *path; int maxpath, len; struct stat fst; - if (!pathlist || !file) { /* If either one is NULL, there really isn't much point in going on.... */ return ((const char *) NULL); } @@ -1337,16 +1304,13 @@ search_path(const char *pathlist, const char *file) if ((p = strchr(file, '@')) == NULL) p = strchr(file, '\0'); len = (p - file); - /* leave room for an extra '/' and trailing '\0' */ maxpath = sizeof(name) - (len + 2); if (maxpath <= 0) return NULL; - /* check if we can find it now */ strncpy(name, file, len); name[len] = '\0'; - D_OPTIONS(("Checking for file \"%s\"\n", name)); if (!access(name, R_OK)) { if (stat(name, &fst)) { @@ -1364,21 +1328,17 @@ search_path(const char *pathlist, const char *file) } for (path = pathlist; path != NULL && *path != '\0'; path = p) { int n; - /* colon delimited */ if ((p = strchr(path, ':')) == NULL) p = strchr(path, '\0'); - n = (p - path); if (*p != '\0') p++; - if (n > 0 && n <= maxpath) { if (*path == '~') { unsigned int l; char *home_dir = getenv("HOME"); - if (home_dir && *home_dir) { l = strlen(home_dir); if (l + n < (unsigned) maxpath) { @@ -1394,7 +1354,6 @@ search_path(const char *pathlist, const char *file) name[n++] = '/'; name[n] = '\0'; strncat(name, file, len); - D_OPTIONS(("Checking for file \"%s\"\n", name)); if (!access(name, R_OK)) { if (stat(name, &fst)) { @@ -1423,12 +1382,9 @@ load_image(const char *file, simage_t *simg) Imlib_Image *im; Imlib_Load_Error im_err; char *geom; - ASSERT_RVAL(file != NULL, 0); ASSERT_RVAL(simg != NULL, 0); - D_PIXMAP(("load_image(%s, %8p)\n", file, simg)); - if (*file != '\0') { if ((geom = strchr(file, '@')) != NULL) { *geom++ = 0; @@ -1464,7 +1420,6 @@ void update_cmod(colormod_t *cmod) { ASSERT(cmod != NULL); - /* When a particular R/G/B color modifier is changed, this function must be called to resync the Imlib2 color modifier (imlib_mod) with our new brightness, contrast, and gamma values. */ @@ -1492,9 +1447,7 @@ update_cmod_tables(imlib_t *iml) { colormod_t *mod = iml->mod, *rmod = iml->rmod, *gmod = iml->gmod, *bmod = iml->bmod; DATA8 rt[256], gt[256], bt[256]; - REQUIRE(mod || rmod || gmod || bmod); - /* When any changes is made to any individual color modifier for an image, this function must be called to update the overall Imlib2 color modifier. */ D_PIXMAP(("Updating color modifier tables for %8p\n", iml)); @@ -1510,7 +1463,6 @@ update_cmod_tables(imlib_t *iml) imlib_reset_color_modifier(); } imlib_get_color_modifier_tables(rt, gt, bt, NULL); - if (rmod && rmod->imlib_mod) { imlib_context_set_color_modifier(rmod->imlib_mod); imlib_get_color_modifier_tables(rt, NULL, NULL, NULL); @@ -1525,7 +1477,6 @@ update_cmod_tables(imlib_t *iml) } imlib_context_set_color_modifier(mod->imlib_mod); imlib_set_color_modifier_tables(rt, gt, bt, NULL); - if (mod->brightness != 0x100) { imlib_modify_color_modifier_brightness((double) (mod->brightness - 255.0) / 255.0); } @@ -1559,7 +1510,6 @@ shade_ximage_15(void *data, int bpl, int w, int h, int rm, int gm, int bm) { unsigned char *ptr; int x, y; - ptr = (unsigned char *) data + (w * sizeof(DATA16)); if ((rm <= 256) && (gm <= 256) && (bm <= 256)) { /* No saturation */ @@ -1602,7 +1552,6 @@ shade_ximage_16(void *data, int bpl, int w, int h, int rm, int gm, int bm) { unsigned char *ptr; int x, y; - ptr = (unsigned char *) data + (w * sizeof(DATA16)); if ((rm <= 256) && (gm <= 256) && (bm <= 256)) { /* No saturation */ @@ -1645,7 +1594,6 @@ shade_ximage_32(void *data, int bpl, int w, int h, int rm, int gm, int bm) { unsigned char *ptr; int x, y; - ptr = (unsigned char *) data + (w * 4); if ((rm <= 256) && (gm <= 256) && (bm <= 256)) { /* No saturation */ @@ -1708,7 +1656,6 @@ shade_ximage_24(void *data, int bpl, int w, int h, int rm, int gm, int bm) { unsigned char *ptr; int x, y; - ptr = (unsigned char *) data + (w * 3); if ((rm <= 256) && (gm <= 256) && (bm <= 256)) { /* No saturation */ @@ -1781,10 +1728,8 @@ colormod_trans(Pixmap p, imlib_t *iml, GC gc, unsigned short w, unsigned short h unsigned short rm, gm, bm, shade; Imlib_Color ctab[256]; int real_depth = 0; - D_PIXMAP(("colormod_trans(p == 0x%08x, gc, w == %hu, h == %hu) called.\n", p, w, h)); REQUIRE(p != None); - if (iml->mod) { shade = iml->mod->brightness; } else { @@ -1810,11 +1755,9 @@ colormod_trans(Pixmap p, imlib_t *iml, GC gc, unsigned short w, unsigned short h return; /* Nothing to do */ } D_PIXMAP((" -> rm == %hu, gm == %hu, bm == %hu, shade == %hu\n", rm, gm, bm, shade)); - if (Xdepth <= 8) { XColor cols[256]; - for (i = 0; i < (unsigned long) (1 << Xdepth); i++) { cols[i].pixel = i; cols[i].flags = DoRed | DoGreen | DoBlue; @@ -1828,7 +1771,6 @@ colormod_trans(Pixmap p, imlib_t *iml, GC gc, unsigned short w, unsigned short h } else if (Xdepth == 16) { XWindowAttributes xattr; - XGetWindowAttributes(Xdisplay, desktop_window, &xattr); if ((xattr.visual->green_mask == 0x3e0)) { real_depth = 15; @@ -1913,7 +1855,6 @@ update_desktop_info(int *w, int *h) unsigned int pw, ph, pb, pd; int px, py; Window dummy; - if (w) { *w = 0; } @@ -1966,7 +1907,6 @@ get_desktop_window(void) unsigned char *data; unsigned int nchildren; Window w, root, *children, parent; - D_PIXMAP(("Current desktop window is 0x%08x\n", (unsigned int) desktop_window)); if ((desktop_window != None) && (desktop_window != Xroot)) { XSelectInput(Xdisplay, desktop_window, None); @@ -1975,7 +1915,6 @@ get_desktop_window(void) for (w = TermWin.parent; w; w = parent) { D_PIXMAP((" Current window ID is: 0x%08x\n", w)); - if ((XQueryTree(Xdisplay, w, &root, &parent, &children, &nchildren)) == False) { D_PIXMAP((" Egad! XQueryTree() returned false!\n")); return None; @@ -2023,7 +1962,6 @@ get_desktop_pixmap(void) static Pixmap color_pixmap = None, orig_desktop_pixmap; unsigned long length, after; unsigned char *data; - D_PIXMAP(("Current desktop pixmap is 0x%08x\n", (unsigned int) desktop_pixmap)); if (desktop_pixmap == None) { orig_desktop_pixmap = None; /* Forced re-read. */ @@ -2039,8 +1977,8 @@ get_desktop_pixmap(void) LIBAST_X_FREE_PIXMAP(color_pixmap); color_pixmap = None; } - XGetWindowProperty(Xdisplay, desktop_window, props[PROP_TRANS_PIXMAP], 0L, 1L, False, AnyPropertyType, &type, &format, &length, &after, - &data); + XGetWindowProperty(Xdisplay, desktop_window, props[PROP_TRANS_PIXMAP], 0L, 1L, False, AnyPropertyType, &type, + &format, &length, &after, &data); if (type == XA_PIXMAP) { p = *((Pixmap *) data); XFree(data); @@ -2060,7 +1998,6 @@ get_desktop_pixmap(void) GC gc; XGCValues gcvalue; Screen *scr = ScreenOfDisplay(Xdisplay, Xscreen); - gcvalue.foreground = gcvalue.background = PixColors[bgColor]; gc = LIBAST_X_CREATE_GC(GCForeground | GCBackground, &gcvalue); XGetGeometry(Xdisplay, p, &w, &px, &py, &pw, &ph, &pb, &pd); @@ -2088,13 +2025,12 @@ get_desktop_pixmap(void) } else { XFree(data); } - XGetWindowProperty(Xdisplay, desktop_window, props[PROP_TRANS_COLOR], 0L, 1L, False, AnyPropertyType, &type, &format, &length, &after, - &data); + XGetWindowProperty(Xdisplay, desktop_window, props[PROP_TRANS_COLOR], 0L, 1L, False, AnyPropertyType, &type, + &format, &length, &after, &data); if (type == XA_CARDINAL) { XGCValues gcvalue; GC gc; Pixel pix; - free_desktop_pixmap(); pix = *((Pixel *) data); XFree(data); @@ -2102,7 +2038,6 @@ get_desktop_pixmap(void) gcvalue.foreground = pix; gcvalue.background = pix; gc = LIBAST_X_CREATE_GC(GCForeground | GCBackground, &gcvalue); - color_pixmap = LIBAST_X_CREATE_PIXMAP(16, 16); XFillRectangle(Xdisplay, color_pixmap, gc, 0, 0, 16, 16); D_PIXMAP(("Created solid color pixmap 0x%08x for desktop_pixmap.\n", color_pixmap)); @@ -2133,16 +2068,12 @@ shaped_window_apply_mask(Drawable d, Pixmap mask) { static signed char have_shape = -1; - REQUIRE(d != None); REQUIRE(mask != None); - D_PIXMAP(("shaped_window_apply_mask(d [0x%08x], mask [0x%08x]) called.\n", d, mask)); - # ifdef HAVE_X_SHAPE_EXT if (have_shape == -1) { /* Don't know yet. */ int unused; - D_PIXMAP(("Looking for shape extension.\n")); if (XQueryExtension(Xdisplay, "SHAPE", &unused, &unused, &unused)) { have_shape = 1; @@ -2171,7 +2102,6 @@ set_icon_pixmap(char *filename, XWMHints * pwm_hints) Imlib_Color_Modifier tmp_cmod; XWMHints *wm_hints; int w = 8, h = 8; - if (pwm_hints) { wm_hints = pwm_hints; } else { @@ -2182,15 +2112,12 @@ set_icon_pixmap(char *filename, XWMHints * pwm_hints) tmp_cmod = imlib_create_color_modifier(); imlib_context_set_color_modifier(tmp_cmod); imlib_reset_color_modifier(); - if (filename && *filename) { if ((icon_path = search_path(rs_path, filename)) == NULL) icon_path = search_path(getenv(PATH_ENV), filename); - if (icon_path != NULL) { XIconSize *icon_sizes; int count, i; - temp_im = imlib_load_image_with_error_return(filename, &im_err); if (temp_im == NULL) { print_error("Unable to load icon file \"%s\" -- %s\n", filename, imlib_strerror(im_err)); @@ -2240,10 +2167,8 @@ set_icon_pixmap(char *filename, XWMHints * pwm_hints) wm_hints->flags |= IconWindowHint; } imlib_free_image_and_decache(); - wm_hints->icon_x = wm_hints->icon_y = 0; wm_hints->flags |= IconPositionHint; - /* Only set the hints ourselves if we were passed a NULL pointer for pwm_hints */ if (!pwm_hints) { XSetWMHints(Xdisplay, TermWin.parent, wm_hints); diff --git a/src/scream.h b/src/scream.h index 223bab4..b4332ad 100644 --- a/src/scream.h +++ b/src/scream.h @@ -33,6 +33,7 @@ #define NS_SCREEN_ST_CLR 12 #define NS_EFUN_NOT_SET 13 #define NS_USER_CXL 14 +#define NS_NOT_ALLOWED 15 #define NS_ERR_WEIRDSCREEN 1 @@ -50,6 +51,11 @@ #define NS_HOP_DOWN 0 #define NS_HOP_UP 1 +#define NS_ESC_CMDLINE 1 +#define NS_ESC_SYSSCREENRC 2 +#define NS_ESC_SCREENRC 3 +#define NS_ESC_INTERACTIVE 4 + /***************************************************************************/ @@ -82,9 +88,12 @@ typedef struct __ns_sess { /* a whole screen-session with many clients */ ssh-key should be on the remote machine. */ char *rsrc; /* add'l parameter to screen/scream. URL-enc */ char *home; /* user's home dir. so we can find .screenrc */ + char *sysrc; /* global screen config */ void *userdef; /* the term-app can store a pointer here */ int fd; /* fd for communication */ char escape,literal; /* talking to screen: defaults to ^A, a */ + int escdef; /* where was the escape sequence defined? */ + int delay; /* initialization delay */ int dsbb; /* default length of scroll-back buffer */ struct __ns_efuns *efuns; /* callbacks into the terminal program. */ struct __ns_hop *hop; /* tunnel, if any */ @@ -130,6 +139,7 @@ typedef struct __ns_efuns { /* callbacks into the terminal program */ int (*inp_text)(void *,int,char *); int (*inp_dial)(void *,char *,int,char **,int (*)(void *,char *,size_t,size_t)); int (*inp_tab)(void *,char *[],int,char *,size_t,size_t); + int (*waitstate)(void *,int); } _ns_efuns; @@ -153,6 +163,7 @@ _ns_efuns *ns_dst_efuns(_ns_efuns **); _ns_efuns *ns_get_efuns(_ns_sess *,_ns_disp *); /* debug */ +void ns_desc_string(char *,char *); void ns_desc_hop(_ns_hop *,char *); void ns_desc_sess(_ns_sess *,char *); @@ -167,15 +178,18 @@ _ns_sess *ns_attach_by_URL(char *,char *,_ns_efuns **,int *,void *); /* send command to screen */ int ns_screen_command(_ns_sess *, char *); -/* send statement to screen */ +/* send statement to screen (prefixing it with the session's ^A: equiv) */ int ns_screen_xcommand(_ns_sess *,char , char *); -/* parse and forward a screen-statement */ -int ns_parse_screen_cmd(_ns_sess *,char *); +/* parse and forward a screen-statement (from ^A: input or screenrc) */ +int ns_parse_screen_cmd(_ns_sess *,char *,int); /* parse and forward a screen-hotkey */ int ns_parse_screen_key(_ns_sess *,char); +/* parse and forward a string */ +int ns_parse_screen_interactive(_ns_sess *, char *); + /* parse screen escape setup */ char ns_parse_esc(char **); @@ -222,6 +236,7 @@ void ns_register_txt(_ns_efuns *,int (*inp_text)(void *,int,char *)); void ns_register_inp(_ns_efuns *,int (*)(void *,char *,int,char **,int (*)(void *,char *,size_t,size_t))); void ns_register_tab(_ns_efuns *,int (*)(void *,char *[],int,char *,size_t,size_t)); +void ns_register_fun(_ns_efuns *,int (*)(void *,int)); diff --git a/src/screamcfg.h b/src/screamcfg.h index 71359d6..8ae78e0 100644 --- a/src/screamcfg.h +++ b/src/screamcfg.h @@ -16,19 +16,23 @@ #define NS_PARANOID /* define NS_DEBUG to get debug-info. no support for those who undef this. */ -#undef NS_DEBUG +#undef NS_DEBUG /* debug memory stuff. never actually used this. */ #undef NS_DEBUG_MEM +#define NS_MAXCMD 512 + #define NS_SSH_CALL "ssh" #define NS_SSH_OPTS "-t" #define NS_SSH_TUNNEL_OPTS "-N" -#define NS_SCREAM_CALL "scream" +#define NS_SCREAM_CALL "scream %s" #define NS_SCREAM_OPTS "-xRR" -#define NS_SCREEN_CALL "screen" +#define NS_SCREEN_CALL "screen %s" #define NS_SCREEN_OPTS "-xRR" -#define NS_SCREEM_CALL "\"" NS_SCREAM_CALL " " NS_SCREAM_OPTS " 2>/dev/null || " NS_SCREEN_CALL " " NS_SCREEN_OPTS "\"" +#define NS_SCREEN_GREP "grep escape \"$SCREENRC\" 2>/dev/null || grep escape ~/.screenrc 2>/dev/null || grep escape \"$SYSSCREENRC\" 2>/dev/null || grep escape /etc/screenrc 2>/dev/null || grep escape /usr/local/etc/screenrc 2>/dev/null || echo \"escape ^Aa\"\n" +#define NS_SCREEM_CALL "%s 2>/dev/null || %s" +#define NS_WRAP_CALL "export TERM=vt100; %s" #define NS_SCREEN_RC ".screenrc" /* this should never change. the escape-char for an out-of-the-box "screen". @@ -44,7 +48,8 @@ else is used in the session, libscream will convert it on the fly. */ /* DO NOT use \005Lw for your status, it breaks older screens!! */ #define NS_SCREEN_UPDATE "\x01w" -#define NS_SCREEN_INIT "\x01:hardstatus lastline\r\x01:defhstatus \"\\005w\"\r\x01:hstatus \"\\005w\"\r\x01:msgminwait 0\r\x01:msgwait 1\r\x01:nethack off\r" NS_SCREEN_UPDATE +#define NS_SCREEN_INIT "\x0c\x01Z\x01:hardstatus lastline\r\x01:defhstatus \"\\005w\"\r\x01:hstatus \"\\005w\"\r\x01:msgminwait 0\r\x01:msgwait 1\r\x01:nethack off\r" NS_SCREEN_UPDATE +#define NS_SCREEN_PRVS_REG "\x01:focus up\r" #define NS_DFLT_SSH_PORT 22 #define NS_MIN_PORT 1025 @@ -62,6 +67,9 @@ a bit of a last resort. */ #define NS_SCREEN_UPD_FREQ 0 +/* should be 1s */ +#define NS_INIT_DELAY 1 + /* how many seconds to wait for an SSH-tunnel to build when using the -Z option (tunnel through firewall). 2 for very fast networks, much more for slow connections. */ diff --git a/src/screen.c b/src/screen.c index 682c97a..67e3c0d 100644 --- a/src/screen.c +++ b/src/screen.c @@ -52,7 +52,10 @@ static rend_t **buf_rend = NULL; /* Tab stop locations */ static char *tabs = NULL; -static screen_t screen = { +#ifndef ESCREEN +static +#endif +screen_t screen = { NULL, NULL, 0, 0, 0, 0, 0, Screen_DefaultFlags }; @@ -3366,8 +3369,21 @@ xim_get_position(XPoint * pos) void parse_screen_status_if_necessary(void) { + static int hc = 0; ns_parse_screen(TermWin.screen, (TermWin.screen_pending > 1), TermWin.ncol, screen.text[TermWin.nrow + TermWin.saveLines - 1]); if (TermWin.screen_pending > 1) TermWin.screen_pending = 0; +#if 0 + { + FILE *fh; + int c; + if ((fh = fopen("Escreen.log", "a"))) { + for (c = 0; c < 8; c++) + if (strcmp(drawn_text[c], drawn_text[c + 1])) + fprintf(fh, "%2d \"%s\"\n", c, drawn_text[c]); + fclose(fh); + } + } +#endif } #endif diff --git a/src/screen.h b/src/screen.h index 97617df..2190263 100644 --- a/src/screen.h +++ b/src/screen.h @@ -231,6 +231,9 @@ extern unsigned char refresh_all; #ifdef MULTI_CHARSET extern encoding_t encoding_method; #endif +#ifdef ESCREEN +extern screen_t screen; +#endif /************ Function Prototypes ************/ _XFUNCPROTOBEGIN diff --git a/src/startup.c b/src/startup.c index 758e0b1..82e6846 100644 --- a/src/startup.c +++ b/src/startup.c @@ -211,7 +211,7 @@ eterm_bootstrap(int argc, char *argv[]) fputs("You called me \"Eterm\"!\n", stderr); else fputs("Stop calling me funky names!\n", stderr); - fprintf(stderr, "Escreen mode is %d (%d rows, %s)\n", TermWin.screen_mode, TermWin.nrow, rs_url); + fprintf(stderr, "Escreen mode is %d (%d rows, URL is \"%s\")\n", TermWin.screen_mode, TermWin.nrow, rs_url); # endif } #endif