From ec34068f82ad446e54498d6221a1a4145c1cc9f4 Mon Sep 17 00:00:00 2001 From: Michael Jennings Date: Wed, 26 Jun 2002 21:02:12 +0000 Subject: [PATCH] Wed Jun 26 16:58:14 2002 Michael Jennings (mej) Latest Escreen stuff from Azundris, including work on twin support (twin.sourceforge.net). SVN revision: 6330 --- ChangeLog | 5 + configure.in | 33 +++- doc/README.Escreen | 41 ++--- src/buttons.c | 9 + src/command.c | 44 +++-- src/libscream.c | 419 ++++++++++++++++++++++++++++++++------------- src/menus.c | 22 +-- src/options.c | 3 +- src/scream.h | 46 +++-- src/screamcfg.h | 9 +- src/script.c | 9 +- 11 files changed, 449 insertions(+), 191 deletions(-) diff --git a/ChangeLog b/ChangeLog index 017c0e6..c6070db 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4730,3 +4730,8 @@ Thu Jun 20 18:55:59 2002 Michael Jennings (mej) Better fix from Azundris. ---------------------------------------------------------------------- +Wed Jun 26 16:58:14 2002 Michael Jennings (mej) + +Latest Escreen stuff from Azundris, including work on twin support +(twin.sourceforge.net). +---------------------------------------------------------------------- diff --git a/configure.in b/configure.in index 45cb3d3..4f0e59f 100644 --- a/configure.in +++ b/configure.in @@ -361,12 +361,40 @@ AC_MSG_CHECKING(for Escreen support) AC_ARG_ENABLE(escreen, [ --enable-escreen enable Eterm's built-in screen support], [ if test "$enableval" = "yes"; then - AC_MSG_RESULT(yes) - AC_DEFINE(ESCREEN) + AC_CHECK_PROG(FOUND_SCREEN, screen, screen) + if test ! -z "$FOUND_SCREEN"; then + AC_DEFINE(NS_HAVE_SCREEN,1,[Support the GNU screen text windowing system?]) + else + AC_WARN(*** screen support has been disabled because screen was not found ***) + fi else AC_MSG_RESULT(no) fi], AC_MSG_RESULT(no) ) +AC_MSG_CHECKING(for Etwin support) +AC_ARG_ENABLE(etwin, +[ --enable-etwin enable Eterm's built-in twin support], [ + if test "$enableval" = "yes"; then + AC_CHECK_LIB(Tw, Tw_Open, FOUND_LIBTWIN=1, FOUND_LIBTWIN=0, $GRLIBS) + if test "$FOUND_LIBTWIN" -ne "1"; then + AC_WARN(*** Twin support has been disabled because libTw was not found ***) + else + AC_DEFINE(NS_HAVE_TWIN,1,[Support the twin text windowing system?]) + LIBS="$LIBS -lTw" + fi + else + AC_MSG_RESULT(no) + fi], AC_MSG_RESULT(no) +) + +if test ! -z "FOUND_$SCREEN" || ! -z "$FOUND_LIBTWIN"; then + AC_DEFINE(ESCREEN) +fi + +if test ! -z "FOUND_$SCREEN" || ! -z "$FOUND_LIBTWIN"; then + AC_DEFINE(ESCREEN) +fi + AC_MSG_CHECKING(if profiling macros should be included) AC_ARG_ENABLE(profile, [ --enable-profile compile with code profiling macros enabled], [ @@ -866,6 +894,7 @@ AC_ARG_WITH(sense-of-humor, [ --without-sense-of-humor Specify this if you ha if test -z "$HUMOR"; then AC_CHECK_LIB(Kenny, life_signs, , [ echo " Oh my god, they killed Kenny! You bastards!" + AC_DEFINE(HAVE_HUMOR,1,[Does user have a sense of humour?]) ]) fi diff --git a/doc/README.Escreen b/doc/README.Escreen index 4d5d7af..a34ca4f 100644 --- a/doc/README.Escreen +++ b/doc/README.Escreen @@ -6,7 +6,7 @@ | _/ ___ \ |_| | _ _ | |___\__ \ (__| | | __/ __/ | | | |_|/_/ \_\__\_\ (_|_) |_____|___/\___|_| \___|\___|_| |_| -Frequently Asked Questions about the Eterm "Escreen" extension +Frequently Asked Questions about the "Escreen/Etwin" extension @@ -86,22 +86,21 @@ A An Eterm should open with a screen (without a status-line) running Q What's new? -* Dialog boxes now longer block the entire GUI (only Eterm's). +* libscream's functions are available through Eterm's scripting + facility. See escreen.cfg for an example. -* Display-closing has a dialog-box now. +* Preliminary Twin support. For now, Twin-URLs (Eterm -U twin://) + and Twin's mouse-protocol are supported, allowing you start twin + within Eterm (making it the only terminal emulator to support Twin, + AFAIK). Next release should feature Twin support through libscream + (thus exposing Twin to button- and key-bindings through Eterm's + scripting interface). -* Code clean-up. It's actually understandable now. - (You can also compile libscream w/o support for screen now. : ) - -* Logs debug info through libast now if it available - -* Fix for scrollbar (reported by mej). - -* Fix for remote sessions with no corresponding local user - (reported by tfing). + For more information on Twin see + http://freshmeat.net/projects/twin/?topic_id=158 * Tear-off tabs. You can select the button-representation of a - display and drag-and-drop it + display and drag-and-drop it [currently under reconstruction] - to another button: @@ -123,9 +122,6 @@ Q What should I expect in the future? (TODO) * Limited support for scrolling. screen doesn't give us all the info we'd need to make this really sexy. -* Possibly support for enhanced screen-clones (like the perchance - forthcoming "scream"). - ------------------------------------------------------------------------------ @@ -142,7 +138,7 @@ A If you call it an Eterm, it will behave like one. Same for an Escreen. (you'd have to symlink from Escreen to Eterm first, of course). Additionally, when called with a command-line (-e "/some/program"), the suite will *always* behave like an Eterm, even if invoked as Escreen. - Likewise, when called with an URL (-U "screen://user@some.host.gov/"), + Likewise, when called with an URL (-U screen://user@some.host.gov/), it will behave like an Escreen, even if invoked under another name. @@ -154,7 +150,7 @@ A Before you complain: * Take a deep breath, remember you didn't pay for this. * Check whether you are using the latest version. Support for each - version stops with the release of a new one! + version ceases with the release of a new one! * Read all of the FAQ, your question may be answered in there. Remember that the FAQ grows with almost each release, so re-reading @@ -201,9 +197,10 @@ A Well, yes. ^A talks to the screen program. Put a line to press to send the escape (^A in the example) to the application instead); you'll want to put something else to move it around. See "man screen" for details. - 2002/05/13 note that ^A: opens a buffer where you can directly enter - statements like "escape ^Uu"; trying things out will be - easier that way. yes, it will be ^U: afterwards. ; ) + + Note that ^A: opens a buffer where you can directly enter + statements like "escape ^Uu"; trying things out will be + easier that way. Yes, it the magic key will be ^U: afterwards. ; ) @@ -230,7 +227,7 @@ Q Escreen changes the escape on the remote box to the same thing as on A You can always override the escapes like so: - Eterm -U user@host.com/-e^Xy + Eterm -U screen://user@host.com/-e^Xy Where ^X is the escape and y the literal (man screen). diff --git a/src/buttons.c b/src/buttons.c index 7247860..354d36a 100644 --- a/src/buttons.c +++ b/src/buttons.c @@ -1090,10 +1090,19 @@ bbar_draw(buttonbar_t *bbar, unsigned char image_state, unsigned char force_mode GC gc; /* evil temporary hack */ int f = button->flags & ~NS_SCREAM_BUTTON; + if (f & NS_SCREAM_CURR) { + f = 1; + } else if (f & NS_SCREAM_ACT) { + f = 2; + } else { + f = 0; + } + gc = LIBAST_X_CREATE_GC(0, NULL); XCopyGC(Xdisplay, bbar->gc, GCFont, gc); XSetForeground(Xdisplay, gc, PixColors[minBright + f + 2]); + D_BBAR(("bbar_draw: text \"%s\", colour %d.\n", button->text, f)); if (f) { draw_string(bbar, bbar->bg, gc, button->text_x, button->text_y, button->text, button->len); LIBAST_X_FREE_GC(gc); diff --git a/src/command.c b/src/command.c index e3fdf57..9922cc0 100644 --- a/src/command.c +++ b/src/command.c @@ -2471,6 +2471,7 @@ upd_disp(void *xd, int n, int flags, char *name) /* Update flags */ if (flags >= 0) { button->flags = (flags | NS_SCREAM_BUTTON); + D_ESCREEN(("upd_disp: new flags for \"%s\": %d\n", button->text, flags)); } /* Redraw buttonbar to reflect new information */ @@ -2571,6 +2572,7 @@ exe_prg(void *xd, char **argv) /****** Azundris' playthings :-) ******/ +#ifdef HAVE_HUMOR #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; @@ -2761,6 +2763,7 @@ waitstate(void *xd, int ms) return 0; } +#endif static _ns_efuns * escreen_reg_funcs(void) @@ -2790,7 +2793,9 @@ escreen_reg_funcs(void) ns_register_inp(efuns, input_dialog); ns_register_tab(efuns, menu_tab); +#ifdef HAVE_HUMOR ns_register_fun(efuns, waitstate); +#endif return efuns; } @@ -2798,15 +2803,22 @@ escreen_reg_funcs(void) static int make_escreen_menu(buttonbar_t *bbar) { + static int been_here = 0; button_t *button; menu_t *m; menuitem_t *i; + if (been_here) { /* the start function may be called more than once */ + return 0; /* in later versions, but we only want one EScreen menu */ + } + + been_here = 1; + if ((m = menu_create(NS_MENU_TITLE))) { char *sc[] = { /* display functions */ - "New", "es_display(new)", /* \x01:screen\r */ - "New (w/ name)...", "es_display(new,ask)", + "New", "es_display(new)", /* \x01:screen\r */ + "New...", "es_display(new,ask)", "Rename...", "es_display(name,ask)", "Backlog...", "es_display(backlog)", "Monitor", "es_display(monitor)", @@ -2815,7 +2827,7 @@ make_escreen_menu(buttonbar_t *bbar) /* region functions */ "Split", "es_region(new)", "Unsplit", "es_region(full)", - "Prev region", "es_region(prev)", /* NS_SCREEN_PRVS_REG */ + "Prev region", "es_region(prev)", /* NS_SCREEN_PRVS_REG */ "Next region", "es_region(next)", "Kill region", "es_region(kill)", "-", "", @@ -2883,7 +2895,7 @@ escreen_init(char **argv) _ns_efuns *efuns; buttonbar_t *bbar; - if (!TermWin.screen_mode) { + if (TermWin.screen_mode == NS_MODE_NONE) { return run_command(argv); } @@ -2905,7 +2917,8 @@ escreen_init(char **argv) bbar_add(bbar); } - if ((TermWin.screen = ns_attach_by_URL(rs_url, rs_hop, &efuns, &ns_err, bbar)) == 0) { + if ((TermWin.screen = ns_attach_by_URL(rs_url, rs_hop, &efuns, &ns_err, bbar)) == NULL) { + D_CMD(("ns_attach_by_URL(%s,%s) failed\n", rs_url, rs_hop)); return -1; } if (rs_delay >= 0) { @@ -2920,6 +2933,7 @@ escreen_init(char **argv) parent_resize(); /* add_screen_ctl_button(bbar,"New",'c'); */ + D_CMD(("TermWin.screen->fd = %d\n", TermWin.screen->fd)); return TermWin.screen->fd; } #endif @@ -2963,7 +2977,7 @@ init_command(char **argv) AT_LEAST((int) num_fds, pipe_fd + 1); } if ((cmd_fd = command_func(argv)) < 0) { - print_error("aborting\n"); + print_error("Unable to run sub-command.\n"); exit(EXIT_FAILURE); } } @@ -3140,15 +3154,19 @@ cmd_getc(void) # ifdef NS_HAVE_TWIN case NS_MODE_TWIN: if (!TermWin.screen->twin) { - if (!Tw_CheckMagic(libscream_magic)) { - D_ESCREEN(("ns_attach_by_sess: Tw_CheckMagic failed\n")); - TermWin.screen->backend = TermWin.screen_mode = NS_MODE_NONE; - } else { - if (!(TermWin.screen->twin = Tw_Open(TermWin.screen->twin_str))) { - D_ESCREEN(("ns_attach_by_sess: Tw_Open(%s) failed\n", TermWin.screen->twin_str)); + if (!TermWin.screen->timestamp) { + TermWin.screen->timestamp = time(NULL); + } else if (TermWin.screen->timestamp < time(NULL)) { + if (!Tw_CheckMagic(libscream_magic)) { + D_ESCREEN(("ns_attach_by_sess: Tw_CheckMagic failed\n")); TermWin.screen->backend = TermWin.screen_mode = NS_MODE_NONE; } else { - D_ESCREEN(("ns_attach_by_sess: Tw_Open(%s) succeeded\n", TermWin.screen->twin_str)); + if (!(TermWin.screen->twin = Tw_Open(TermWin.screen->twin_str))) { + ns_desc_twin(TermWin.screen, "cmd_getc->Tw_Open"); + TermWin.screen->backend = TermWin.screen_mode = NS_MODE_NONE; + } else { + D_ESCREEN(("ns_attach_by_sess: Tw_Open(%s) succeeded: handle @ %p\n", TermWin.screen->twin_str, TermWin.screen->twin)); + } } } } diff --git a/src/libscream.c b/src/libscream.c index 7ed353c..a3f4d0a 100644 --- a/src/libscream.c +++ b/src/libscream.c @@ -19,6 +19,7 @@ * 2002/05/21 Azundris code restructuring, basic tab tear-off * 2002/06/04 Azundris advanced tab tear-off * 2002/06/05 Azundris basic twin support + * 2002/06/11 Azundris more twin support ***************************************************************************/ @@ -61,6 +62,7 @@ #ifdef NS_HAVE_TWIN # include # include +# include #endif #ifndef MAXPATHLEN @@ -387,6 +389,8 @@ ns_new_sess(void) s->dsbb = NS_SCREEN_DEFSBB; s->delay = NS_INIT_DELAY; s->fd = -1; + s->disp = -1; + s->port = -1; if (sa) { /* add to end of list */ _ns_sess *r = sa; @@ -632,6 +636,28 @@ ns_sess_init(_ns_sess * sess) +/* return port number for service TWIN. + <- a port number -- 7754 in all likelihood. */ + +int +ns_get_twin_port(void) +{ +#ifdef NS_HAVE_TWIN + static int port = 0; + struct servent *srv; + + if (port) + return port; + /* (fixme) replace with getservbyname_r on systems that have it */ + srv = getservbyname("twin", "tcp"); + return (port = (srv ? ntohs(srv->s_port) : TW_INET_PORT)); +#else + return -1; +#endif +} + + + /* return port number for service SSH (secure shell). <- a port number -- 22 in all likelihood. */ @@ -755,6 +781,28 @@ ns_desc_string(char *c, char *doc) +/* ns_desc_twin + print status of a twin session + sess the session + doc info about the context + !stderr info about the twin session */ + +void +ns_desc_twin(_ns_sess * sess, char *doc) +{ +#ifdef HAVE_TWIN + if (!sess) { + D_ESCREEN(("%s: ns_desc_twin called with broken pointer!\n", doc ? doc : "")); + return; + } + D_ESCREEN(("%s: twin status (%s) is %d-%s, %d-%s\n", doc, sess->twin_str, + Tw_Errno(sess->twin), + Tw_StrError(sess->twin, Tw_Errno(sess->twin)), Tw_ErrnoDetail(sess->twin), Tw_StrErrorDetail(sess->twin, Tw_Errno(sess->twin), Tw_ErrnoDetail(sess->twin)))); +#endif +} + + + /* 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() @@ -764,8 +812,8 @@ ns_desc_string(char *c, char *doc) static void ns_desc_hop(_ns_hop * h, char *doc) { - if (!h && doc) { - D_ESCREEN(("%s: ns_desc_hop called with broken pointer!\n", doc)); + if (!h) { + D_ESCREEN(("%s: ns_desc_hop called with broken pointer!\n", doc ? doc : "")); return; } @@ -788,16 +836,18 @@ static void ns_desc_sess(_ns_sess * sess, char *doc) { if (!sess) { - D_ESCREEN(("%s: ns_desc_sess called with broken pointer!\n", doc)); + D_ESCREEN(("%s: ns_desc_sess called with broken pointer!\n", doc ? doc : "")); return; } if (sess->where == NS_LCL) - D_ESCREEN(("%s: (efuns@%p)\t (user %s) local %s %s\n", doc, sess->efuns, sess->user, sess->proto, sess->rsrc)); + D_ESCREEN(("%s: (efuns@%p)\t (user %s) local %s", doc, sess->efuns, sess->user, sess->proto)); else { - D_ESCREEN(("%s: (efuns@%p)\t %s://%s%s%s@%s:%s/%s\n", - doc, sess->efuns, sess->proto ? sess->proto : "???", sess->user, sess->pass ? ":" : "", sess->pass ? sess->pass : "", sess->host, - sess->port, sess->rsrc)); + D_ESCREEN(("%s: (efuns@%p)\t %s://%s%s%s@%s", + doc, sess->efuns, sess->proto ? sess->proto : "???", sess->user, sess->pass ? ":" : "", sess->pass ? sess->pass : "", sess->host)); + if (sess->port != NS_DFLT_SSH_PORT) + D_ESCREEN((":%s", sess->port)); } + D_ESCREEN(("%c%s\n", sess->where == NS_LCL ? ' ' : '/', sess->rsrc)); if (sess->hop) ns_desc_hop(sess->hop, NULL); if (sess->sysrc) @@ -1088,23 +1138,6 @@ ns_attach_by_sess(_ns_sess ** sp, int *err) D_ESCREEN(("ns_attach_by_sess: screen session-fd is %d, ^%c-%c\n", sess->fd, sess->escape + 'A' - 1, sess->literal)); -#ifdef NS_HAVE_TWIN_ - if (sess->backend == NS_MODE_TWIN) { - sleep(2); - if (!Tw_CheckMagic(libscream_magic)) { - D_ESCREEN(("ns_attach_by_sess: Tw_CheckMagic failed\n")); - goto fail; - } else { - if (!(sess->twin = Tw_Open(sess->twin_str))) { - D_ESCREEN(("ns_attach_by_sess: Tw_Open(%s) failed\n", sess->twin_str)); - goto fail; - } - D_ESCREEN(("ns_attach_by_sess: Tw_Open() succeeded\n")); - ns_desc_sess(sess, "ns_sess_init"); - } - } -#endif - return sess; fail: @@ -1145,18 +1178,22 @@ ns_attach_by_URL(char *url, char *hop, _ns_efuns ** ef, int *err, void *xd) err = &err_dummy; *err = NS_OOM; - if (!sess) + if (!sess) { + D_ESCREEN(("ns_attach_by_URL: no session...\n")); return NULL; + } + + D_ESCREEN(("ns_attach_by_URL(%s,%s,%p,%p,%p)\n", url, hop, *ef, err, xd)); if (url && strlen(url)) { char *q; - if (!(d = STRDUP(url))) + if (!(d = strdup(url))) goto fail; if ((q = strstr(d, "://"))) { /* protocol, if any */ *q = '\0'; - if (!(sess->proto = STRDUP(d))) + if (!(sess->proto = strdup(d))) goto fail; q += 3; } else @@ -1169,15 +1206,15 @@ ns_attach_by_URL(char *url, char *hop, _ns_efuns ** ef, int *err, void *xd) *p = '\0'; if ((r = strchr(q, ':'))) { /* password, if any */ *(r++) = '\0'; - if (!(sess->pass = STRDUP(r))) /* password may be empty string! */ + if (!(sess->pass = strdup(r))) /* password may be empty string! */ goto fail; } - sess->user = STRDUP(q); + sess->user = strdup(q); } q = p + 1; } - if ((p = strchr(q, '/'))) { + if ((p = strchr(q, '/'))) { /* rsrc, possibly url-encoded */ *(p++) = '\0'; if (strlen(p)) { char *r = p; @@ -1210,6 +1247,25 @@ ns_attach_by_URL(char *url, char *hop, _ns_efuns ** ef, int *err, void *xd) r++; } else { if (*r == '-') { +# ifdef NS_HAVE_TWIN + if (!strncmp(NS_TWIN_PARA, &r[1], strlen(NS_TWIN_PARA))) { + char *y = strchr(r, '@'); + + if (y && *++y) { + char *z = strchr(y, ':'); + + if (z) { + *z++ = '\0'; + if (*z) + sess->disp = atoi(z); + if (sess->disp < 0 || sess->disp > NS_MAX_PORT) + sess->disp = 0; + } + if (strlen(y)) + sess->host = strdup(y); + } + } else +# endif # ifdef NS_HAVE_SCREEN if (*(++r) == 'e') { /* set escape */ char x = 0, y = 0; @@ -1228,7 +1284,7 @@ ns_attach_by_URL(char *url, char *hop, _ns_efuns ** ef, int *err, void *xd) *rx = '\0'; if (*r != '/') D_ESCREEN(("URL: path for screen's option -c should be absolute (%s)\n", r)); - if ((rc = STRDUP(r))) { + if ((rc = strdup(r))) { if (sess->home) /* this should never happen */ FREE(sess->home); D_ESCREEN(("URL: searching for rc in %s\n", rc)); @@ -1238,8 +1294,9 @@ ns_attach_by_URL(char *url, char *hop, _ns_efuns ** ef, int *err, void *xd) r = rx; *rx = ' '; } - } + } else # endif + ; while (*r && (f || *r != ' ')) { if (*r == '\"') f = 1 - f; @@ -1251,7 +1308,7 @@ ns_attach_by_URL(char *url, char *hop, _ns_efuns ** ef, int *err, void *xd) } } - if (!(sess->rsrc = STRDUP(p))) + if (!(sess->rsrc = strdup(p))) goto fail; } } @@ -1260,11 +1317,12 @@ ns_attach_by_URL(char *url, char *hop, _ns_efuns ** ef, int *err, void *xd) *(p++) = '\0'; if (!*p || !(sess->port = atoi(p)) || sess->port > NS_MAX_PORT) { *err = NS_MALFORMED_URL; + D_ESCREEN(("malformed URL...\n")); goto fail; } } - if (strlen(q) && !(sess->host = STRDUP(q))) /* host, if any */ + if (strlen(q) && !(sess->host = strdup(q))) /* host, if any */ goto fail; FREE(d); @@ -1275,27 +1333,30 @@ ns_attach_by_URL(char *url, char *hop, _ns_efuns ** ef, int *err, void *xd) if (!sess->user) { /* default user (current user) */ if (!pwe) { *err = NS_UNKNOWN_USER; + D_ESCREEN(("unknown user...\n")); goto fail; } - if (!(sess->user = STRDUP(pwe->pw_name))) + if (!(sess->user = strdup(pwe->pw_name))) goto fail; - } else if ((sess->host && strcmp(sess->host, "localhost") && strcmp(sess->host, "127.0.0.1")) || sess->port) { + } else if ((sess->host && strcmp(sess->host, "localhost") && strcmp(sess->host, "127.0.0.1")) || (sess->port > 0)) { pwe = NULL; } else if (!pwe || strcmp(pwe->pw_name, sess->user)) { /* user!=current_user */ sess->where = NS_SU; if (!(pwe = getpwnam(sess->user))) { *err = NS_UNKNOWN_USER; + D_ESCREEN(("unknown user...\n")); goto fail; } } else { *err = NS_UNKNOWN_USER; + D_ESCREEN(("unknown user...\n")); goto fail; } #ifdef NS_HAVE_SCREEN if (getenv("SYSSCREENRC")) { /* $SYSSCREENRC */ - if (!(sess->sysrc = STRDUP(getenv("SCREENRC")))) + if (!(sess->sysrc = strdup(getenv("SCREENRC")))) goto fail; } else { char *loc[] = { "/usr/local/etc/screenrc", /* official */ @@ -1307,56 +1368,96 @@ ns_attach_by_URL(char *url, char *hop, _ns_efuns ** ef, int *err, void *xd) for (n = 0; n < nloc; n++) if (!access(loc[n], R_OK)) { - if (!(sess->sysrc = STRDUP(loc[n]))) + if (!(sess->sysrc = strdup(loc[n]))) goto fail; n = nloc; } } if (getenv("SCREENRC")) { /* $SCREENRC */ - sess->home = STRDUP(getenv("SCREENRC")); + sess->home = strdup(getenv("SCREENRC")); } 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); } #endif - if (!sess->host) { /* no host */ - if (!(sess->host = STRDUP("localhost"))) - goto fail; - if (!sess->port) { /* no host/port */ - sess->where = NS_LCL; - } - } else if ((p = strchr(sess->host, '/'))) /* have host */ - *p = '\0'; - - if (!sess->port) /* no port -> default port (SSH) */ - sess->port = ns_get_ssh_port(); - sess->backend = NS_MODE_NEGOTIATE; if (sess->proto) { #ifdef NS_HAVE_SCREEN if (!strcmp(sess->proto, "screen")) { sess->backend = NS_MODE_SCREEN; } else +#warning compiling in support for GNU screen #endif #ifdef NS_HAVE_TWIN +#warning compiling in support for twin if (!strcmp(sess->proto, "twin")) { char *twd = getenv("TWDISPLAY"); sess->backend = NS_MODE_TWIN; - if (!sess->twin_str) - sess->twin_str = STRDUP(twd ? twd : ":0"); + + /* fall back on TWDISPLAY env var only if host not set yet */ + if (twd && (!sess->host || !strlen(sess->host) || !strcmp(sess->host, "localhost"))) { + char *twdisp = strrchr(twd, ':'); + + if (twdisp) { + *twdisp++ = '\0'; + if (*twdisp && sess->disp < 0) /* fall back on TWDISPLAY display */ + sess->disp = atoi(twdisp); + } /* fall back on TWDISPLAY host */ + if (((!sess->host) || (!strlen(sess->host))) && strlen(twd) && strcmp(twd, "localhost")) + sess->host = strdup(twd); + } + /* this is ugly, but does the intuitive thing. + * if you specifically want to connect a twin to a non-twin + * port < 20, make it unambiguous by using the syntax + * twin://host.dom:port/-twin@:disp or + * twin://:port/-twin@host.dom:disp */ + else if (sess->host && sess->disp < 0 && sess->port >= 0 && sess->port < 20) { + sess->disp = sess->port; + sess->port = -1; + } } else #endif if (!strcmp(sess->proto, "scream")) { sess->backend = NS_MODE_SCREAM; } else { *err = NS_UNKNOWN_PROTO; + D_ESCREEN(("unknown protocol %s...\n", sess->proto)); + fprintf(stderr, "protocol \"%s\" not known...\n", sess->proto); goto fail; } } + if ((sess->disp < 0) || (sess->disp > NS_MAX_PORT)) + sess->disp = 0; + +#ifdef NS_HAVE_TWIN + /* do this *before* host-fallback */ + if (sess->twin_str) + FREE(sess->twin_str); + + if (sess->twin_str = MALLOC((sess->host ? strlen(sess->host) : 0) + 7)) + sprintf(sess->twin_str, "%s:%d", (sess->host ? sess->host : ""), sess->disp); +#endif + + if (!sess->host) { /* no host */ + if (!(sess->host = strdup("localhost"))) + goto fail; + if (sess->port <= 0) { /* no host/port */ + sess->where = NS_LCL; + } + } else if ((p = strchr(sess->host, '/'))) /* have host */ + *p = '\0'; + + if (sess->port <= 0) { /* no port -> default port (SSH) */ + if (sess->backend == NS_MODE_TWIN) + sess->port = ns_get_twin_port(); + else + sess->port = ns_get_ssh_port(); + } + if (!sess->efuns && ef && *ef) { sess->efuns = ns_ref_efuns(ef); } @@ -1370,12 +1471,15 @@ ns_attach_by_URL(char *url, char *hop, _ns_efuns ** ef, int *err, void *xd) } *err = NS_SUCC; + return ns_attach_by_sess(&sess, err); fail: if (d) FREE(d); + D_ESCREEN(("ns_attach_by_URL: fail...\n")); + return ns_dst_sess(&sess); } @@ -1457,7 +1561,7 @@ ns_go2_disp(_ns_sess * s, int d) return ns_screen_command(s, b); break; #endif -#ifdef NS_HAVE_TWIN_ +#ifdef NS_HAVE_TWIN case NS_MODE_TWIN: { tscreen ts = Tw_FirstScreen(s->twin); @@ -1477,23 +1581,27 @@ ns_go2_disp(_ns_sess * s, int d) } } -/* toggle monitor mode for disp (if possible) */ +/* toggle monitor mode for disp (if possible). -1 for current disp */ int -ns_mon_disp(_ns_sess * s, int no) +ns_mon_disp(_ns_sess * s, int no, int quiet) { if (!s) return NS_FAIL; + D_ESCREEN(("toggling monitoring for display %d\n", no)); + switch (s->backend) { #ifdef NS_HAVE_SCREEN case NS_MODE_SCREEN: - ns_go2_disp(s, no); + if (no >= 0) + ns_go2_disp(s, no); + if (quiet == NS_MON_TOGGLE_QUIET) + s->flags |= NS_SESS_NO_MON_MSG; return ns_screen_command(s, "\x01M"); break; #endif - default: - return NS_FAIL; } + return NS_FAIL; } /* scrollback buffer mode (if any) */ @@ -1553,7 +1661,13 @@ ns_rel_disp(_ns_sess * s, int d) ns_go2_disp(s, x->index); } -/* add a client display with the name "name" after display number #after */ + + +/* add a client display and a tab. + s the session to add to + after add after this display (0..n). -1 to add before disp 0. + name NULL: ask. "": let backend choose name. else: set name. */ + int ns_add_disp(_ns_sess * s, int after, char *name) { @@ -1569,9 +1683,9 @@ ns_add_disp(_ns_sess * s, int after, char *name) if (after >= 0) ns_go2_disp(s, after); if (ns_screen_command(s, "\x01\x03") == NS_SUCC) { - /* yes, -1 for "current_display" works even though we just made a new - display that isn't in our list yet. faith will see you through. */ - ns_ren_disp(s, -1, name); + if (!name || strlen(name)) + ns_ren_disp(s, -2, name); + ns_mon_disp(s, -2, NS_MON_TOGGLE_QUIET); } break; #endif @@ -1585,6 +1699,7 @@ ns_add_disp(_ns_sess * s, int after, char *name) } + /* move client display #fm to display slot #to */ int ns_mov_disp(_ns_sess * s, int fm, int to) @@ -1679,7 +1794,15 @@ ns_rem_disp(_ns_sess * s, int d, int ask) return ret; } -/* rename display #d to "name". if d==-1, use current */ +/* rename display + s session display is in + d -1 current display + -2 display was just created and is not in list yet + >=0 index of the display + name NULL ask for name + !NULL the name + <- error code */ + int ns_ren_disp(_ns_sess * s, int d, char *name) { @@ -1696,13 +1819,16 @@ ns_ren_disp(_ns_sess * s, int d, char *name) return NS_FAIL; } - if (d < 0) { + if (d == -1) d = s->curr->index; - } if (!name || !*name) { /* ask */ - i = s->curr->name; - l = strlen(i); + if (d == -2) + l = 32; /* dirty, but effective */ + else { + i = s->curr->name; + l = strlen(i); + } (void) ns_inp_dial(s, "Enter a new name for the current display", 12, &i, NULL); if (!i || !*i) return NS_FAIL; @@ -1712,7 +1838,8 @@ ns_ren_disp(_ns_sess * s, int d, char *name) #ifdef NS_HAVE_SCREEN case NS_MODE_SCREEN: if ((n = MALLOC(strlen(i ? i : name) + l + 1))) { - ns_go2_disp(s, d); + if (d >= 0) + ns_go2_disp(s, d); strcpy(&n[l], i ? i : name); /* copy new name */ while (l) /* prepend backspaces */ n[--l] = '\x08'; @@ -2238,29 +2365,25 @@ ns_screen_command(_ns_sess * sess, char *cmd) char *c; int ret = NS_SUCC; - D_ESCREEN(("sess %8p, cmd %8p\n", sess, cmd)); if (!cmd || !*cmd) return NS_FAIL; - D_ESCREEN(("Sending screen command %s\n", safe_print_string(cmd, strlen(cmd)))); if (NS_EFUN_EXISTS(efuns, sess, NULL, inp_text)) { - D_ESCREEN((" -> inp_text is set\n")); - if ((c = STRDUP(cmd))) { - char *p = c; /* replace default escape-char with that */ + if ((c = strdup(cmd))) { + { + char *p = c; /* replace default escape-char with that */ - D_ESCREEN((" -> translating escapes\n")); - while (*p) { /* actually used in this session */ - if (*p == NS_SCREEN_ESCAPE) - *p = sess->escape; - p++; + while (*p) { /* actually used in this session */ + if (*p == NS_SCREEN_ESCAPE) + *p = sess->escape; + p++; + } } ns_desc_string(c, "ns_screen_command: xlated string"); efuns->inp_text(NULL, sess->fd, c); FREE(c); - } else { - D_ESCREEN((" -> out of memory\n")); + } else ret = NS_OOM; - } } /* out of memory */ else { ret = NS_EFUN_NOT_SET; @@ -2549,7 +2672,7 @@ ns_parse_screen_interactive(_ns_sess * sess, char *c) if (!c || !*c) return NS_FAIL; #ifdef NS_PARANOID - if (!(s = o = STRDUP(c))) + if (!(s = o = strdup(c))) return NS_FAIL; #else s = c; @@ -2576,6 +2699,32 @@ ns_parse_screen_interactive(_ns_sess * sess, char *c) +/* ns_weird_screen -- damage control + screen the offending session + doc string specifying the context + !stderr a description of the problem + !err_inhibit the problem-type is marked so we don't rewarn. + <- error code (always NS_FAIL) */ + +static int +ns_screen_weird(_ns_sess * screen, long type, char *doc) +{ + if (!(err_inhibit & type)) { + err_inhibit |= type; + fprintf(stderr, "parse_screen: %s (%ld) screen sent weird stuff.\n" + "This should never happen. It is assumed that you use a\n" + "rather unusual configuration for \"screen\". Please\n" + "send the result of 'screen --version' to \n" + "(together with your ~/.screenrc and /etc/screenrc if present).\n" + "If at all possible, please also run 'Eterm -e screen' and make\n" + "a screenshot of the offending window (and the window only, the\n" "beauty of your desktop is not relevant to this investigation. : ).\n", doc, type); + } + (void) ns_upd_stat(screen); + return NS_FAIL; +} + + + /* 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 @@ -2663,6 +2812,7 @@ ns_parse_screenrc(_ns_sess * s, char *fn, int whence) as certain functionalities ("add a tab", "show status message") may be called from here. p the offending message-line + ! mode of operation may be modified using screen->flags <- returns an error code. */ static int @@ -2670,8 +2820,9 @@ ns_parse_screen_msg(_ns_sess * screen, char *p) { _ns_efuns *efuns; char *p2; - char vdate[33], vtype[3], vrem[17]; - int ma, mi, mu, ret = NS_SUCC, type; + char vdate[33], vtype[3], vrem[17], win[64]; + int ma, mi, mu, ret = NS_SUCC, type, n; + size_t l; if (!p) return NS_FAIL; @@ -2681,6 +2832,8 @@ ns_parse_screen_msg(_ns_sess * screen, char *p) while (isspace(*p)) p++; + D_ESCREEN(("got \"%s\"\n", p)); + type = (strlen(p) > 1) ? NS_SCREEN_STATUS : NS_SCREEN_ST_CLR; if (type == NS_SCREEN_ST_CLR) { @@ -2701,7 +2854,7 @@ ns_parse_screen_msg(_ns_sess * screen, char *p) if (screen->name) { FREE(screen->name); } - if ((screen->name = STRDUP(&p[strlen(NS_SCREEN_SESS_T)]))) { + if ((screen->name = strdup(&p[strlen(NS_SCREEN_SESS_T)]))) { size_t lsn = strlen(screen->name); if (lsn) { @@ -2715,7 +2868,30 @@ ns_parse_screen_msg(_ns_sess * screen, char *p) !strncmp(p, "msgminwait", strlen("msgminwait")) || !strcmp(p, "Press ^@ to destroy or ^@ to resurrect window") || !strcmp(p, "Aborted because of window size change.")) p = NULL; - else if (sscanf(p, NS_SCREEN_VERSION_T, vtype, &ma, &mi, &mu, vrem, vdate) == 6) { + else if ((screen->flags & NS_SESS_NO_MON_MSG) && + ((sscanf(p, "Window %d (%s) is now being monitored for all activity.", &n, win) == 2) || + (sscanf(p, "Window %d (%s) is no longer being monitored for activity.", &n, win) == 2))) { + D_ESCREEN(("activity toggled quietly for window %d-%s\n", n, win)); + p = NULL; + screen->flags = (screen->flags & ~NS_SESS_NO_MON_MSG); /* reset mute flag */ + } else if (!strncmp(p, NS_SCREEN_ACT_T, l = strlen(NS_SCREEN_ACT_T))) { + if (NS_EFUN_EXISTS(efuns, screen, NULL, upd_disp)) { + int inx, button; + _ns_disp *d; + + p += l; + inx = atoi(p); + button = disp_get_real_by_screen(screen, inx); + if ((d = disp_fetch(screen, inx))) { + D_ESCREEN(("activity in window %d-%s (button %d)\n", inx, d->name, button)); + d->flags |= NS_SCREAM_ACT; + efuns->upd_disp(screen->userdef, button, d->flags, NULL); + } else { + D_ESCREEN(("activity in unknown window %d (button %d)...\n", inx, button)); + } + } + p = NULL; + } else if (sscanf(p, NS_SCREEN_VERSION_T, vtype, &ma, &mi, &mu, vrem, vdate) == 6) { if (!strcmp("en", vtype)) screen->backend = NS_MODE_SCREEN; else if (!strcmp("am", vtype)) @@ -2779,7 +2955,7 @@ ns_parse_screen(_ns_sess * screen, int force, int width, char *p) if (!force && screen->timestamp) return NS_SUCC; - if ((p = STRDUP(p))) { + if ((p = strdup(p))) { _ns_parse pd[NS_MAX_DISPS]; p2 = &p[width - 1]; @@ -2788,13 +2964,19 @@ ns_parse_screen(_ns_sess * screen, int force, int width, char *p) *(p2--) = '\0'; } /* p2 now points behind last item */ - D_ESCREEN(("parse_screen: screen sends ::%s::\n", p)); + D_ESCREEN(("parse_screen: screen sends (%d) ::%s::\n", strlen(p), p)); 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 */ + disp->flags &= ~NS_SCREAM_ACT; + while (disp->next) { + disp->flags &= ~NS_SCREAM_CURR; + disp = disp->next; + } ret = ns_upd_stat(screen); + D_ESCREEN(("parse_screen: qeueing update\n")); } /* more than once */ else if (!screen->timestamp) { /* send init string the first time around, just to be on @@ -2820,7 +3002,7 @@ ns_parse_screen(_ns_sess * screen, int force, int width, char *p) screen->timestamp = 1; D_ESCREEN(("parse_screen: resetting screen...\n")); } else { - D_ESCREEN(("parse_screen: error, we should never get here\n")); + D_ESCREEN(("parse_screen: nothing to do in exception, updating anyways...\n")); ret = ns_upd_stat(screen); } FREE(p); @@ -2880,28 +3062,42 @@ ns_parse_screen(_ns_sess * screen, int force, int width, char *p) n = pd[r].screen; disp = disp_fetch(screen, n); + if (pd[r].flags & NS_SCREAM_CURR) { + pd[r].flags &= ~NS_SCREAM_ACT; + } + if (!disp) { /* new display */ - if (!(disp = disp_fetch_or_make(screen, n)) || !(disp->name = STRDUP(pd[r].name))) { + if (!(disp = disp_fetch_or_make(screen, n)) || !(disp->name = strdup(pd[r].name))) { D_ESCREEN(("parse_screen: out of memory in new_display(%d)\n", n)); ret = NS_FAIL; } else { if (NS_EFUN_EXISTS(efuns, screen, NULL, ins_disp)) ret = efuns->ins_disp(screen->userdef, pd[r].real - 1, pd[r].screen, disp->name); } - } else if ((tmp = strcmp(disp->name, pd[r].name)) || /* upd display */ - (disp->flags != pd[r].flags)) { - if (tmp) { - FREE(disp->name); - if (!(disp->name = STRDUP(pd[r].name))) { - FREE(p); - return NS_FAIL; + } else { + int fl = (disp->flags & ~NS_SCREAM_CURR) | (pd[r].flags & NS_SCREAM_MASK); + + if ((fl & (NS_SCREAM_CURR | NS_SCREAM_ACT)) == (NS_SCREAM_CURR | NS_SCREAM_ACT)) + fl &= ~NS_SCREAM_ACT; + + if ((tmp = strcmp(disp->name, pd[r].name)) || /* upd display */ + (disp->flags != fl)) { + if (tmp) { + FREE(disp->name); + if (!(disp->name = strdup(pd[r].name))) { + FREE(p); + return NS_FAIL; + } } + if (disp->flags != fl) { + if (pd[r].flags & NS_SCREAM_CURR) + disp->sess->curr = disp; + disp->flags = fl; + } else + fl = -1; + if (NS_EFUN_EXISTS(efuns, screen, NULL, upd_disp)) + ret = efuns->upd_disp(screen->userdef, r, fl, (!tmp) ? NULL : disp->name); } - if (pd[r].flags & NS_SCREAM_CURR) - disp->sess->curr = disp; - disp->flags = pd[r].flags & NS_SCREAM_MASK; - 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 @@ -2925,19 +3121,9 @@ ns_parse_screen(_ns_sess * screen, int force, int width, char *p) #ifdef NS_PARANOID if (!r) { - if (!(err_inhibit & NS_ERR_WEIRDSCREEN)) { - err_inhibit |= NS_ERR_WEIRDSCREEN; - fprintf(stderr, "parse_screen: !r\n" - "This should never happen. It is assumed that you use a\n" - "rather unusual configuration for \"screen\". Please\n" - "send the result of 'screen --version' to \n" - "(together with your ~/.screenrc and /etc/screenrc if present).\n" - "If at all possible, please also run 'Eterm -e screen' and make\n" - "a screenshot of the offending window (and the window only, the\n" "beauty of your desktop is not relevant to this investigation. : ).\n"); - } - ret = ns_upd_stat(screen); + D_ESCREEN(("parse_screen: no elements parsed (!r)...\n")); FREE(p); - return NS_FAIL; + return ns_screen_weird(screen, NS_ERR_WEIRDSCREEN, "no elements parsed (!r)..."); } else #endif /* kill overhang (o/t right) if status-line isn't side-scrolling @@ -3024,6 +3210,7 @@ ns_register_red(_ns_efuns * efuns, int (*redraw) (void *)) efuns->redraw = redraw; } + /* function that redraw part of the terminal */ void ns_register_rda(_ns_efuns * efuns, int (*redraw_xywh) (void *, int, int, int, int)) @@ -3031,7 +3218,7 @@ ns_register_rda(_ns_efuns * efuns, int (*redraw_xywh) (void *, int, int, int, in efuns->redraw_xywh = redraw_xywh; } -/* function that redraw part of the terminal */ +/* function that expires buttons */ void ns_register_exb(_ns_efuns * efuns, int (*expire_buttons) (void *, int)) { diff --git a/src/menus.c b/src/menus.c index 7a4198c..629aa26 100644 --- a/src/menus.c +++ b/src/menus.c @@ -302,7 +302,9 @@ menu_handle_button_release(event_t *ev) menu_display_submenu(current_menu, item); } else { menu_action(item); - menuitem_deselect(current_menu); + if (current_menu) { + menuitem_deselect(current_menu); + } } } /* Reset the state of the menu system. */ @@ -413,8 +415,7 @@ menu_dispatch_event(event_t *ev) return (0); } -menulist_t * -menulist_add_menu(menulist_t *list, menu_t *menu) +menulist_t *menulist_add_menu(menulist_t *list, menu_t *menu) { ASSERT_RVAL(menu != NULL, list); @@ -446,8 +447,7 @@ menulist_clear(menulist_t *list) FREE(list); } -menu_t * -menu_create(char *title) +menu_t *menu_create(char *title) { menu_t *menu; static Cursor cursor; @@ -599,8 +599,7 @@ menu_is_child(menu_t *menu, menu_t *submenu) return 0; } -menu_t * -find_menu_by_title(menulist_t *list, char *title) +menu_t *find_menu_by_title(menulist_t *list, char *title) { register unsigned char i; @@ -614,8 +613,7 @@ find_menu_by_title(menulist_t *list, char *title) return NULL; } -menu_t * -find_menu_by_window(menulist_t *list, Window win) +menu_t *find_menu_by_window(menulist_t *list, Window win) { register unsigned char i; @@ -629,8 +627,7 @@ find_menu_by_window(menulist_t *list, Window win) return NULL; } -menuitem_t * -find_item_by_coords(menu_t *menu, int x, int y) +menuitem_t *find_item_by_coords(menu_t *menu, int x, int y) { register unsigned char i; register menuitem_t *item; @@ -700,8 +697,7 @@ menuitem_change_current(menuitem_t *item) } } -menuitem_t * -menuitem_create(char *text) +menuitem_t *menuitem_create(char *text) { menuitem_t *menuitem; diff --git a/src/options.c b/src/options.c index ead932d..eabc029 100644 --- a/src/options.c +++ b/src/options.c @@ -323,8 +323,7 @@ static const struct { OPT_LONG("finished-text", "text to output after program termination", &rs_finished_text), OPT_LONG("term-name", "value to use for setting $TERM", &rs_term_name), OPT_LONG("pipe-name", "filename of console pipe to emulate -C", &rs_pipe_name), - OPT_STR('a', "attribute", "parse an attribute in the specified context", NULL), - OPT_BOOL('C', "console", "grab console messages", &Options, Opt_console), + OPT_STR('a', "attribute", "parse an attribute in the specified context", NULL), OPT_BOOL('C', "console", "grab console messages", &Options, Opt_console), #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), diff --git a/src/scream.h b/src/scream.h index a2eee78..1910d97 100644 --- a/src/scream.h +++ b/src/scream.h @@ -58,7 +58,7 @@ #define NS_SCREAM_FILE 32 #define NS_SCREAM_SHARED 64 #define NS_SCREAM_ZOMBIE 128 -#define NS_SCREAM_BUTTON 0xf0 +#define NS_SCREAM_BUTTON 0xf00 #define NS_SCREAM_MASK (~(NS_SCREAM_UTMP|NS_SCREAM_PRVS)) @@ -70,6 +70,11 @@ #define NS_ESC_SCREENRC 3 #define NS_ESC_INTERACTIVE 4 +#define NS_SESS_NO_MON_MSG 1 + +#define NS_MON_TOGGLE_QUIET 0 +#define NS_MON_TOGGLE_NOISY 1 + /***************************************************************************/ @@ -90,35 +95,43 @@ typedef struct __ns_hop { typedef struct __ns_sess { /* a whole screen-session with many clients */ + char *name; /* session name */ int where; /* local/remote */ - int backend; /* screen/scream */ + int backend; /* screen/scream/twin */ int nesting; /* 0=topLevel, 1=screen within a screen etc */ - time_t timestamp; /* last updated when? see NS_SCREEN_UPD_FREQ */ + time_t timestamp; /* last updated when? */ + int delay; /* initialization delay */ + + int flags; /* miracle flags, see NS_SESS_* */ + int fd; /* fd for communication */ + int dsbb; /* default length of scroll-back buffer */ + char *proto; /* protocol. usually "screen" */ char *host; /* host. numeric or symbolic. ("localhost") */ int port; /* port. usually TCP22: SSH */ + int disp; /* display (used by twin etc., not screen) */ char *user; /* user. often current local user */ char *pass; /* password. used for su. for remote sessions, a 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 */ - char *name; /* session name */ - 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 */ struct __ns_disp *dsps; /* first display (that with the lowest index) */ struct __ns_disp *curr; /* current display (NULL for none) */ struct __ns_sess *prvs; /* previous session in session list */ struct __ns_sess *next; /* next session in session list */ + + char *home; /* user's home dir. so we can find .screenrc */ + char *sysrc; /* global screen config */ + char escape,literal; /* talking to screen: defaults to ^A, a */ + int escdef; /* where was the escape sequence defined? */ + #ifdef NS_HAVE_TWIN - tdisplay twin; - char *twin_str; + tdisplay twin; /* twin-display */ + char *twin_str; /* twin-display (string specifier) */ #endif } _ns_sess; @@ -190,9 +203,14 @@ _ns_sess *ns_attach_by_sess(_ns_sess **,int *); _ns_sess *ns_attach_by_URL(char *,char *,_ns_efuns **,int *,void *); int ns_detach(_ns_sess **); +/* debug */ +void ns_desc_twin(_ns_sess *,char *); + /* convenience */ int ns_run(_ns_efuns *, char *); int ns_get_ssh_port(void); +int ns_get_twin_port(void); + int disp_get_real_by_screen(_ns_sess *,int); int disp_get_screen_by_real(_ns_sess *,int); @@ -236,7 +254,7 @@ int ns_rsz_disp(_ns_sess *,int,int,int); int ns_rem_disp(_ns_sess *,int,int); int ns_ren_disp(_ns_sess *,int,char *); int ns_log_disp(_ns_sess *,int,char *); -int ns_mon_disp(_ns_sess *,int); +int ns_mon_disp(_ns_sess *,int,int); int ns_sbb_disp(_ns_sess *,int); int ns_tog_region(_ns_sess *,_ns_disp *); diff --git a/src/screamcfg.h b/src/screamcfg.h index f4504a8..d5fbfa9 100644 --- a/src/screamcfg.h +++ b/src/screamcfg.h @@ -15,12 +15,6 @@ undef it, you're on your own. */ #define NS_PARANOID -/* compile in support for the GNU "screen" program as a backend */ -#define NS_HAVE_SCREEN 1 - -/* compile in support for the "twin" program as a backend */ -#undef NS_HAVE_TWIN - #define NS_MAXCMD 512 @@ -38,6 +32,8 @@ #define NS_SCREEN_RC ".screenrc" #define NS_TWIN_CALL "export TERM=xterm; twin %s" #define NS_TWIN_OPTS "-hw=tty" +#define NS_TWIN_PARA "twin@" +#define NS_TWDISPLAY_OPTS "-" NS_TWIN_PARA "%s" /* this should never change. the escape-char for an out-of-the-box "screen". don't change this just because you set something else in your .screenrc */ @@ -69,6 +65,7 @@ #define NS_SCREEN_SESS_T "This session is named '" #define NS_SCREEN_VERSION_T "scre%2s %d.%d.%d %16s %32s" #define NS_SCREEN_NO_DEBUG "Sorry, screen was compiled without -DDEBUG option." +#define NS_SCREEN_ACT_T "Activity in window " /* should be 1s */ #define NS_INIT_DELAY 1 diff --git a/src/script.c b/src/script.c index bc10066..ffaf571 100644 --- a/src/script.c +++ b/src/script.c @@ -484,12 +484,15 @@ script_handler_es_display(char **params) D_ESCREEN(("Toggle display\n")); ns_tog_disp(sess); } else if (!strcmp(p, "new")) { - if (!a || !*a || !strcasecmp(a, "ask")) { + if (!a || !*a) { + D_ESCREEN(("disp new\n")); + ns_add_disp(sess, no, ""); + } else if (!a || !*a || !strcasecmp(a, "ask")) { D_ESCREEN(("disp new ask\n")); ns_add_disp(sess, no, NULL); } else { D_ESCREEN(("disp new \"%s\"\n", a)); - ns_ren_disp(sess, no, a); + ns_add_disp(sess, no, a); } } else if (!strcmp(p, "title") || !strcmp(p, "name") || !strcmp(p, "rename")) { if (!a || !*a || !strcasecmp(a, "ask")) { @@ -509,7 +512,7 @@ script_handler_es_display(char **params) } } else if (!strcmp(p, "watch") || !strcmp(p, "monitor")) { D_ESCREEN(("Monitor display %d\n", no)); - ns_mon_disp(sess, no); + ns_mon_disp(sess, no, NS_MON_TOGGLE_NOISY); } else if (!strcmp(p, "back") || !strcmp(p, "backlog") || !strcmp(p, "scrollback")) { D_ESCREEN(("View scrollback on display %d\n", no)); ns_sbb_disp(sess, no);