Mon May 13 18:46:06 2002 Michael Jennings (mej)

Latest Escreen patch from Azundris <hacks@azundris.com>.


SVN revision: 6251
eterm-0.10
Michael Jennings 21 years ago
parent aa6f4b3a77
commit 0bdd7edc63
  1. 4
      ChangeLog
  2. 15
      doc/Eterm.1.in
  3. 116
      src/README.Escreen
  4. 5
      src/actions.c
  5. 140
      src/buttons.c
  6. 2
      src/buttons.h
  7. 235
      src/command.c
  8. 906
      src/libscream.c
  9. 190
      src/menus.c
  10. 8
      src/menus.h
  11. 2
      src/options.c
  12. 1
      src/options.h
  13. 5
      src/pixmap.c
  14. 87
      src/scream.h
  15. 58
      src/screamcfg.h
  16. 2
      src/screen.c
  17. 23
      src/term.c

@ -4643,3 +4643,7 @@ Tue May 7 10:16:56 2002 Michael Jennings (mej)
configure.in and configure.ac should no longer differ, so let's not
maintain both.
----------------------------------------------------------------------
Mon May 13 18:46:06 2002 Michael Jennings (mej)
Latest Escreen patch from Azundris <hacks@azundris.com>.
----------------------------------------------------------------------

@ -621,6 +621,21 @@ Pick up a "screen" session at
rather than a local one. URLs look like so (screen://user@host.dom/options),
with all parts optional, defaulting to current user at localhost,
respectively. Forces Escreen mode, overrides \-\-exec.
.TP
.BI \-Z " lclport:fw:fwport,delay" ", \-\-fw " lclport:fw:fwport,delay
The URL given to \-U is in an intranet behind firewall
.I fw
so we'll build an SSH-tunnel to that firewall (to port 22/SSH, or
.I fwport
if given) from our local machine (using any available port-number, or
.I lclport
if given). Then, after
.I delay
seconds (or a sensible default if not given), we will try to open a
screen session on the host behind the firewall using
.I ssh -p localport ... localhost screen
cf.
.I ssh -L
.SH THEMES

@ -21,23 +21,16 @@ there can be no newbie support at this time.
2 - How do I get it?
You already have all you need. Now, compile with ESCREEN defined in
the DEFS in src/Makefile.
If you don't know how to do that, sorry, but you're not Escreen's
intended audience at this point; please hold on.
You already have it. ./configure --enable-escreen && make && make install
Oh, and you also need the screen program. In our tests, we used
$ screen -version
Screen version 3.09.11 (FAU) 14-Feb-02
Screen version 3.09.11 (FAU) 14-Feb-02.
3 - How do I start it?
If you call it an Eterm, it will behave like one. Same for an Escreen.
(ln -s Eterm Escreen; ./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/"),
@ -49,13 +42,41 @@ it will behave like an Escreen, even if invoked under another name.
An Eterm should open with a screen (without a status-line) running
inside of it. There should be a button-bar in the Eterm enumerating
the multiplexed terminal (you usually start with one). If you normally
don't use a button-bar, Escreen will create one for you. Otherwise, it
will add buttons to your existing bar.
the multiplexed terminal (you usually start with one), and button with
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.
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
tab-completion
* support for screen command-line options:
Eterm -U screen://localhost/-xRR+-c~/.screenrc.testing
* menu for "screen"-functions (if you add your own, use ^A as the
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
5 - What should I expect in the future? (TODO)
* support for SSH-tunneling through firewalls
6 - 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. There will likely be limited
@ -63,31 +84,37 @@ will add buttons to your existing bar.
on remote machine), and possibly support for enhanced screen-clones
(like the perchance forthcoming "scream").
* Support for ".screenrc". This was temporarily disabled to aid in
debugging and will soon return in conjunction with
* Escreen accepting non-default key setups and
* menus for "screen"-functions so those unfamiliar with the program
will not need to learn a dozen arcance key-sequences (or even get
used to ^A meaning something new).
9 - FAQ
Q I don't see any buttons!
Q I don't see any buttons when I connect to a remote screen!
A 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. : (
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. You will be able to move
that to a key of your choice with the next release.
A Well, yes. ^A talks to the screen program. Put a line
like "escape ^Aa" in "~/.screenrc". The example declares
Control-A (^A) to be the magic key (and ^A-a what you need
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. ; )
Q I typed ^A and it *doesn't do* funny things!
A You probably already have changed the magic escape key to something
other than ^A (on the command-line, within Escreen, or in .screenrc).
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.
@ -101,15 +128,30 @@ A Escreen cannot run "screen". If you do have "screen", and it is in
the search path, screen apparently terminates right away. Normally
this means that your screen-sessions are messed up; "screen -ls" will
give you a list of them; "screen -wipe" will do the cleaning up.
NOTE: If this happens with a remote session, the remote end might just
find our terminal type confusing. The "--term-name" option with some-
thing vanilla (--term-name vt100) should remedy this.
If this happens with a remote session, the remote end might just find
your terminal type confusing. The "--term-name" option with something
vanilla (--term-name vt100) should remedy this.
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 "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.
The code, however, is GPL'd, and its use is documented by example of
Eterm. If you can work with that, do.
The code, however, is LGPL'd, and its use is documented by example of
Eterm (grep for ESCREEN). If you can work with that, do.
Q What's with the licence changing?
A I wrongly assumed that Eterm was GPL'd rather than BSD'd, so I stuck
a GPL on the first alpha. To correct this mistake, the licence was
changed. In an attempt to honour both the convictions of the authors
of Eterm (BSD licence) and those of screen (GPL) which Escreen tries
to bring together, it appears that the licensing of Escreen should
land somewhere in the middle; therefore, I nominally chose LGPL.
This may be softened to BSD at a later date.
Q Who's responsible for this?
@ -120,4 +162,4 @@ A Escreen is an Eterm extension conceived and written by Azundris.
you agree that anything happening while or because of using it is
your fault, and your fault only.
-- Azundris 2002/05/03 <escreen@azundris.com> http://www.azundris.com/
-- Azundris 2002/05/13 <scream@azundris.com> http://www.azundris.com/

@ -59,6 +59,11 @@ action_handle_echo(event_t *ev, action_t *action)
{
USE_VAR(ev);
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);
else
#endif
tt_write((unsigned char *) action->param.string, strlen(action->param.string));
return 1;
}

@ -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
static inline void draw_string(buttonbar_t *, Drawable, GC, int, int, char *, size_t);
@ -226,7 +229,7 @@ bbar_handle_button_press(event_t *ev)
}
if (bbar->current) {
bbar_click_button(bbar, bbar->current);
button_check_action(bbar, bbar->current, 1, ev->xbutton.time);
button_check_action(bbar, bbar->current, ev->xbutton.button, ev->xbutton.time);
}
return 1;
}
@ -768,6 +771,8 @@ bbar_click_button(buttonbar_t *bbar, button_t *button)
void
button_check_action(buttonbar_t *bbar, button_t *button, unsigned char press, Time t)
{
static unsigned char prvs = 0;
switch (button->type) {
case ACTION_MENU:
if (press) {
@ -781,6 +786,36 @@ button_check_action(buttonbar_t *bbar, button_t *button, unsigned char press, Ti
break;
case ACTION_ECHO:
if (!press) {
#ifdef ESCREEN
if(TermWin.screen_mode&&TermWin.screen) { /* translate escapes */
if(prvs!=1) {
button_t *b=bbar->buttons;
_ns_disp *d2=TermWin.screen->dsps;
int n=(button->action.string)[1]-'0';
while(b&&!(b->flags&NS_SCREAM_CURR)) /* find active disp */
b=b->next; /* when trying to change name of non- */
if(b&&b!=button) { /* active display, make that disp active */
button->flags|=NS_SCREAM_CURR; b->flags&=~NS_SCREAM_CURR;
bbar_draw(bbar, IMAGE_STATE_CURRENT, MODE_MASK);
button->flags&=~NS_SCREAM_CURR; b->flags|=NS_SCREAM_CURR;
while(d2 && d2->index != n)
d2 = d2->next;
if(d2)
TermWin.screen->curr=d2; /* pre-adjust curr ptr */
else
fprintf(stderr,NS_PREFIX "button_check_action: no display %d in this session : (\n",n);
(void)ns_screen_command(TermWin.screen,button->action.string); }
if(prvs==2) /* middle button -- kill */
(void)ns_parse_screen_key(TermWin.screen,NS_SCREEN_KILL);
else /* right button -- rename */
(void)ns_parse_screen_key(TermWin.screen,NS_SCREEN_RENAME); }
else /* left button -- select */
(void)ns_screen_command(TermWin.screen,button->action.string); }
else /* not in screen-mode, use normal facilities */
#endif
tt_write((unsigned char *) button->action.string, strlen(button->action.string));
}
break;
@ -792,6 +827,7 @@ button_check_action(buttonbar_t *bbar, button_t *button, unsigned char press, Ti
default:
break;
}
prvs=press;
}
unsigned char
@ -906,7 +942,7 @@ bbar_draw(buttonbar_t *bbar, unsigned char image_state, unsigned char force_mode
gcvalue.foreground = PixColors[button->flags + 2];
gcvalue.font = bbar->font->fid;
if (button->flags && (gc = LIBAST_X_CREATE_GC(GCForeground | GCFont, &gcvalue))) {
if(button->flags&&(gc=LIBAST_X_CREATE_GC(GCForeground | GCFont, &gcvalue))) {
draw_string(bbar, bbar->bg, gc, button->text_x, button->text_y, button->text, button->len);
XFreeGC(Xdisplay, gc);
} else
@ -1015,3 +1051,103 @@ bbar_calc_docked_height(register unsigned char dock_flag)
D_BBAR(("Returning %d\n", h));
return h;
}
/* redraw a button bar */
void
bbar_redraw(buttonbar_t *bbar)
{
bbar_calc_button_sizes(bbar);
bbar_calc_button_positions(bbar);
bbar_draw(bbar, IMAGE_STATE_CURRENT, MODE_MASK);
}
/* insert a button to the given bar, at the given position.
create a new bar if required.
bar the bar
button the button
after insert after this button (-1 for before first button)
addright add to rbuttons instead of buttons
<- NULL, or the bar */
buttonbar_t *
bbar_insert_button(buttonbar_t *bbar, button_t *button, int after, int addright)
{
int state = 1;
if (!bbar) {
if (!(bbar = bbar_create())) {
fprintf(stderr, "ins_disp: failed to create button-bar...\n");
return NULL;
} else {
bbar->next=NULL;
bbar_set_font(bbar, "-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1");
bbar_set_docked(bbar, BBAR_DOCKED_TOP);
}
state = 0;
}
if(addright) { /* add to rbuttons */
if (!bbar->rbuttons) { /* first button */
button->next = NULL;
bbar->rbuttons = button;
} else {
int c=0;
button_t *b = bbar->rbuttons;
do {
c++;
} while((b=b->next));
if(after>=(c-1)) {
button->next=bbar->rbuttons;
bbar->rbuttons=button; }
else {
b = bbar->rbuttons;
after=c-after-2;
while (after-- > 0 && b->next)
b = b->next;
button->next = b->next;
b->next = button; }
}
}
else { /* add to buttons */
if (!bbar->buttons || after < 0) { /* first button */
button->next = bbar->buttons;
bbar->buttons = button;
} else {
button_t *b = bbar->buttons;
while (after-- > 0 && b->next)
b = b->next;
button->next = b->next;
b->next = button;
}
}
bbar->current = button;
/* add to list of bbars so bbar_event_init_dispatcher() won't break */
if (!state) {
if(buttonbar) {
buttonbar_t *bar=buttonbar;
while(bar->next)
bar=bar->next;
bar->next=bbar;
}
else
buttonbar=bbar;
bbar_init(bbar, TermWin.width);
bbar_add(bbar);
}
bbar_redraw(bbar);
if (!state) {
parent_resize();
}
return bbar;
}

@ -140,6 +140,8 @@ extern void bbar_draw_all(unsigned char image_state, unsigned char force_modes);
extern void bbar_calc_positions(void);
extern unsigned long bbar_calc_total_height(void);
extern unsigned long bbar_calc_docked_height(unsigned char);
extern void bbar_redraw(buttonbar_t *bbar);
extern buttonbar_t *bbar_insert_button(buttonbar_t *bbar, button_t *button, int after, int addright);
_XFUNCPROTOEND

@ -128,6 +128,7 @@ static const char cvs_ident[] = "$Id$";
#endif
#include "windows.h"
#include "buttons.h"
#include "menus.h"
#ifdef ESCREEN
# include "screamcfg.h"
@ -2106,7 +2107,7 @@ run_command(char **argv)
char **a = argv;
if (a) {
while (*a) {
puts(*a);
fprintf(stderr, NS_PREFIX "run_command: %s\n",*a);
a++;
}
}
@ -2226,7 +2227,11 @@ run_command(char **argv)
my_euid = my_ruid;
my_egid = my_rgid;
#ifdef HAVE_USLEEP
usleep(10); /* Attempt to force a context switch so that the parent runs before us. */
#else
sleep(1); /* ugliness */
#endif
D_CMD(("[%d] About to spawn shell\n", getpid()));
if (chdir(initial_dir)) {
print_warning("Unable to chdir to \"%s\" -- %s\n", initial_dir, strerror(errno));
@ -2289,55 +2294,61 @@ run_command(char **argv)
int
set_scroll_x(void *xd, int x)
{
printf("set_scroll_x: %d\n", x);
return 0;
fprintf(stderr, NS_PREFIX "set_scroll_x: %d\n", x);
return NS_FAIL;
}
int
set_scroll_y(void *xd, int y)
{
printf("set_scroll_y: %d\n", y);
return 0;
fprintf(stderr, NS_PREFIX "set_scroll_y: %d\n", y);
return NS_FAIL;
}
int
set_scroll_w(void *xd, int w)
{
printf("set_scroll_w: %d\n", w);
return 0;
fprintf(stderr, NS_PREFIX "set_scroll_w: %d\n", w);
return NS_FAIL;
}
int
set_scroll_h(void *xd, int h)
{
printf("set_scroll_h: %d\n", h);
return 0;
fprintf(stderr, NS_PREFIX "set_scroll_h: %d\n", h);
return NS_FAIL;
}
int
redraw(void *xd)
{
puts("redraw");
return 0;
fprintf(stderr, NS_PREFIX "redraw\n");
return NS_FAIL;
}
int
redraw_xywh(void *xd, int x, int y, int w, int h)
{
printf("redraw_xywh: %d,%d %dx%d\n", x, y, w, h);
return 0;
fprintf(stderr, NS_PREFIX "redraw_xywh: %d,%d %dx%d\n", x, y, w, h);
return NS_FAIL;
}
/* redraw a button bar */
void
redraw_buttons(buttonbar_t *bbar)
{
bbar_calc_button_sizes(bbar);
bbar_calc_button_positions(bbar);
bbar_draw(bbar, IMAGE_STATE_CURRENT, MODE_MASK);
}
button_t *screen_button_create(char *text,char code) {
button_t *b;
char p[3];
if(!text||!*text||!(b=button_create(text)))
return NULL;
p[0]=NS_SCREEN_ESCAPE;
p[1]=code;
p[2]='\0';
button_set_action(b, ACTION_ECHO, p);
return b; }
@ -2347,58 +2358,53 @@ redraw_buttons(buttonbar_t *bbar)
int
ins_disp(void *xd, int after, char *name)
{
buttonbar_t *bbar = *((buttonbar_t **) xd);
buttonbar_t *bbar;
button_t *button;
int state = 1;
char p[3] = "\x01x";
if(!xd||!name||!*name)
return NS_FAIL;
bbar = *((buttonbar_t **) xd);
if(!(button=screen_button_create(name,'0' + after + 1)))
return NS_FAIL;
#ifdef NS_DEBUG
fprintf(stderr, "ins_disp: %s after %d...\n", name, after);
fprintf(stderr, NS_PREFIX "ins_disp: %s after %d...\n", name, after);
#endif
if (!bbar) {
if (!(bbar = bbar_create())) {
fprintf(stderr, "ins_disp: failed to create button-bar...\n");
return 0;
} else {
bbar_set_font(bbar, "-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1");
bbar_set_docked(bbar, BBAR_DOCKED_TOP);
}
state = 0;
}
if((bbar=bbar_insert_button(bbar,button,after,FALSE))) {
*((buttonbar_t **) xd) = bbar;
return NS_SUCC; }
button = button_create(name);
p[1] = '0' + after + 1;
button_set_action(button, ACTION_ECHO, p);
if (!bbar->buttons || after < 0) { /* first button */
button->next = bbar->buttons;
bbar->buttons = button;
} else {
button_t *b = bbar->buttons;
while (after-- > 0 && b->next)
b = b->next;
button->next = b->next;
b->next = button;
}
button_free(button);
return NS_FAIL;
}
bbar->current = button;
*((buttonbar_t **) xd) = bbar; /* ugly, but it will remain here till
bbar_event_init_dispatcher()
takes a bbar parameter */
if (!state) {
bbar_init(bbar, TermWin.width);
bbar_add(bbar);
}
redraw_buttons(bbar);
/* add supa-dupa right buttons for screen-features.
if our user's configured a bbar, we'll add to that,
otherwise, we'll create one. */
int
add_screen_ctl_button(buttonbar_t **xd,char *name,char key)
{
buttonbar_t *bbar;
button_t *button;
if (!state) {
parent_resize();
}
if(!xd||!name||!*name)
return NS_FAIL;
bbar = *xd;
return 0;
if(!(button=screen_button_create(name,key)))
return NS_FAIL;
if((bbar=bbar_insert_button(bbar,button,-1,TRUE))) {
*xd = bbar;
return NS_SUCC; }
button_free(button);
return NS_FAIL;
}
@ -2415,11 +2421,11 @@ del_disp(void *xd, int n)
int c;
for (c = 0, b2 = bbar->buttons; b2; c++, b2 = b2->next)
fprintf(stderr, "%02d: \"%s\"\n", c, b2->text);
fprintf(stderr, NS_PREFIX "del_disp: %02d: \"%s\"\n", c, b2->text);
#endif
if (!bbar || !(button = bbar->buttons))
return 0;
return NS_FAIL;
b2 = button = bbar->buttons;
if (!n) {
@ -2430,8 +2436,8 @@ del_disp(void *xd, int n)
while (n-- > 0) {
b2 = button;
if (!(button = button->next)) {
fprintf(stderr, "cannot delete button %d: does not exist...\n", bi);
return -1;
fprintf(stderr, NS_PREFIX "del_disp: cannot delete button %d: does not exist...\n", bi);
return NS_FAIL;
}
}
b2->next = button->next;
@ -2440,17 +2446,15 @@ del_disp(void *xd, int n)
}
#ifdef NS_DEBUG_
fprintf(stderr, "deleting button %d (%s)...\n", bi, button->text);
fprintf(stderr, NS_PREFIX "del_disp: deleting button %d (%s)...\n", bi, button->text);
#endif
button->next = NULL;
button_free(button);
redraw_buttons(bbar);
bbar_redraw(bbar);
*((buttonbar_t **) xd) = bbar; /* ugly */
return 0;
return NS_SUCC;
}
@ -2468,7 +2472,7 @@ upd_disp(void *xd, int n, int flags, char *name)
button_t *button;
if (!bbar || !(button = bbar->buttons))
return 0;
return NS_FAIL;
button = bbar->buttons;
while (n-- > 0 && button->next)
@ -2480,7 +2484,7 @@ upd_disp(void *xd, int n, int flags, char *name)
if (!(button->text = strdup(name))) {
button->len = 0;
return -1;
return NS_OOM;
}
button->len = strlen(name);
@ -2489,11 +2493,9 @@ upd_disp(void *xd, int n, int flags, char *name)
if (flags >= 0)
button->flags = flags;
redraw_buttons(bbar);
bbar_redraw(bbar);
*((buttonbar_t **) xd) = bbar; /* ugly */
return 0;
return NS_SUCC;
}
@ -2502,11 +2504,9 @@ upd_disp(void *xd, int n, int flags, char *name)
int
err_msg(void *xd, int err, char *msg)
{
#ifdef NS_DEBUG
if (err != NS_SCREEN_ST_CLR)
printf("err_msg #%d: \"%s\"\n", err, msg);
#endif
return 0;
if(strlen(msg))
menu_dial(NULL,msg,0,NULL,NULL);
return NS_SUCC;
}
@ -2516,11 +2516,26 @@ int
inp_text(void *xd, int id, char *txt)
{
tt_write(txt, strlen(txt));
return 0;
return NS_SUCC;
}
/* open a dialog */
int
inp_dial(void *xd, char *prompt, int maxlen, char **retstr,
int (*inp_tab)(void *,char *,size_t,size_t))
{
switch(menu_dial(xd, prompt, maxlen, retstr,inp_tab)) {
case 0:
return NS_SUCC;
case -2:
return NS_USER_CXL;
default:
return NS_FAIL; }}
/* run a program (normally "screen") inside the terminal */
int
exe_prg(void *xd, char **argv)
@ -2558,6 +2573,8 @@ init_command(char **argv)
ns_register_exe(efuns, exe_prg);
ns_register_txt(efuns, inp_text);
ns_register_inp(efuns, inp_dial);
ns_register_tab(efuns, menu_tab);
#endif
/* Initialize the command connection. This should be called after
@ -2588,8 +2605,60 @@ init_command(char **argv)
if (!TermWin.screen_mode)
cmd_fd = run_command(argv);
else if ((TermWin.screen = ns_attach_by_URL(rs_url, &efuns, &ns_err, (void *) &buttonbar)))
else if ((TermWin.screen = ns_attach_by_URL(rs_url, rs_hop, &efuns, &ns_err, (void *) &buttonbar))) {
button_t *button;
menu_t *m;
menuitem_t *i;
if((m=menu_create(NS_MENU_TITLE))) {
char *sc[]={ "New", "\x01\x03", "Close", "\x01k" };
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) {
m->font =menu_list->menus[n]->font;
m->fwidth =menu_list->menus[n]->fwidth;
m->fheight=menu_list->menus[n]->fheight;
#ifdef MULTI_CHARSET
m->fontset=menu_list->menus[n]->fontset;
#endif
break; }}}
for(n=0;n<(nsc-1);n+=2) {
if((i=menuitem_create(sc[n]))) {
# ifdef NS_DEBUG
fprintf(stderr, NS_PREFIX "register %s (%d)\n",&sc[n+1][1],*sc[n+1]);
# endif
menuitem_set_action(i,MENUITEM_ECHO,sc[n+1]);
menu_add_item(m,i); }}
if((i=menuitem_create("About..."))) {
menuitem_set_action(i,MENUITEM_ALERT,"Screen compatibility layer by Azundris <scream@azundris.com>");
menu_add_item(m,i); }
if((button=button_create(NS_MENU_TITLE))) {
if(!(buttonbar=bbar_insert_button(buttonbar,button,-1,TRUE))) {
m->font=NULL;
#ifdef MULTI_CHARSET
m->fontset=NULL;
#endif
menu_delete(m);
button_set_action(button,ACTION_STRING,NS_MENU_TITLE);
button_free(button); }
else {
int j,k=menu_list?menu_list->nummenus:0;
menu_list=menulist_add_menu(menu_list,m);
for (j=k;j<menu_list->nummenus;j++)
event_data_add_mywin(&menu_event_data,menu_list->menus[j]->win);
if(!k)
menu_init();
button_set_action(button,ACTION_MENU,NS_MENU_TITLE); }}}
/* add_screen_ctl_button(&buttonbar,"New",'c'); */
cmd_fd = TermWin.screen->fd;
}
# undef ETERM_PREFIX
# undef ESCREEN_PREFIX
if (cmd_fd < 0) {

File diff suppressed because it is too large Load Diff

@ -45,11 +45,17 @@ static const char cvs_ident[] = "$Id$";
#include "windows.h"
menulist_t *menu_list = NULL;
static event_dispatcher_data_t menu_event_data;
#ifndef ESCREEN
static
#endif
event_dispatcher_data_t menu_event_data;
static GC topShadowGC, botShadowGC;
static Time button_press_time;
static int button_press_x = 0, button_press_y = 0;
static menu_t *current_menu;
#ifndef ESCREEN
static
#endif
menu_t *current_menu;
static inline void grab_pointer(Window win);
static inline void ungrab_pointer(void);
@ -719,6 +725,8 @@ menuitem_delete(menuitem_t *item)
FREE(item->action.string);
} else if (item->type == MENUITEM_SCRIPT) {
FREE(item->action.script);
} else if (item->type == MENUITEM_ALERT) {
FREE(item->action.alert);
}
if (item->text) {
FREE(item->text);
@ -766,6 +774,9 @@ menuitem_set_action(menuitem_t *item, unsigned char type, char *action)
case MENUITEM_SCRIPT:
item->action.script = STRDUP(action);
break;
case MENUITEM_ALERT:
item->action.alert = STRDUP(action);
break;
case MENUITEM_STRING:
case MENUITEM_ECHO:
item->action.string = (char *) MALLOC(strlen(action) + 2);
@ -1206,11 +1217,33 @@ menu_action(menuitem_t *item)
cmd_write((unsigned char *) item->action.string, strlen(item->action.string));
break;
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
(void)ns_screen_command(TermWin.screen,item->action.string); }
else
#endif
tt_write((unsigned char *) item->action.string, strlen(item->action.string));
break;
case MENUITEM_SCRIPT:
script_parse((char *) item->action.script);
break;
case MENUITEM_ALERT:
menu_dial(NULL,item->action.alert,0,NULL,NULL);
break;
default:
fatal_error("Internal Program Error: Unknown menuitem type: %u\n", item->type);
break;
@ -1250,3 +1283,156 @@ menu_invoke_by_title(int x, int y, Window win, char *title, Time timestamp)
}
menu_invoke(x, y, win, menu, timestamp);
}
/* tab completion for screen-commands
xd extra-data (current unused)
sc keywords for tab-completion
nsc entries in sc
!b current entry (changes)
l number of characters to compare in current entry
m maximum number of characters in entry (size of input buffer)
<- error code */
int
menu_tab(void *xd,char *sc[],int nsc,char *b,size_t l,size_t m) {
int n,n2=0;
for(n=0;n<nsc;n++) { /* second tab? cycle. */
if((!strcasecmp(b,sc[n]))&&(n<nsc-1)&&!strncasecmp(b,sc[n+1],l)) {
n2=n+1;
break; }}
for(n=n2;n<nsc;n++) {
if(!strncasecmp(b,sc[n],l)) {
if(strcmp(b,sc[n])) {
if(strlen(sc[n])>=m) /* buffer would overflow => fail */
return -1;
strcpy(b,sc[n]);
return 0; }}}
return -1; }
/* open a dialog. this is a bit of a hack and should really resize otf.
xd extra-data (userdef) for inp_tab
prompt the prompt, obviously. required.
maxlen how long the input may get. 0 for an uneditable alert box.
!retstr the address of a pointer. that actual pointer may be NULL,
or point to a default value for the input. after completion,
the pointer will reference the user's input, or be NULL if
the user cancelled input
inp_tab function doing tab-completion, NULL for none
<- error code (0 succ, -1 fail, -2 cancel)
*/
int
menu_dial(void *xd, char *prompt, int maxlen, char **retstr,int (*inp_tab)(void *,char *,size_t,size_t))
{
static unsigned char short_buf[256];
unsigned char *kbuf = short_buf;
menu_t *m;
menuitem_t *i;
register int ch;
int f=0,len,ret=-1,tab=0;
XEvent ev;
KeySym keysym;
char *b,*old;
size_t l;
if(!prompt||!*prompt)
return ret;
if(!maxlen||!retstr) {
inp_tab=NULL;
maxlen=0;
retstr=NULL;
if((b=strdup("Press \"Return\" to continue..."))==NULL)
return ret; }
else {
if(((b=malloc(maxlen+1))==NULL))
return ret;
if(*retstr) {
strncpy(b,*retstr,maxlen);
b[maxlen]='\0'; }
else
b[0]='\0'; }
if((m=menu_create(prompt))) {
for(l=0;l<menu_list->nummenus;l++) { /* copycat font entry to */
if(menu_list->menus[l]->font) { /* blend in with l&f */
m->font =menu_list->menus[l]->font;
m->fwidth =menu_list->menus[l]->fwidth;
m->fheight=menu_list->menus[l]->fheight;
#ifdef MULTI_CHARSET
m->fontset=menu_list->menus[l]->fontset;
#endif
break; }}
if((i=menuitem_create("..."))) {
int h;
old=i->text;
i->text=b;
i->len =strlen(b);
if(m->font) { /* pre-calc width so we can center the dialog */
l=strlen(prompt);
if(i->len>l)
l=XTextWidth(m->font,i->text,i->len);
else
l=XTextWidth(m->font,prompt,l); }
else
l=200;
menuitem_set_action(i,MENUITEM_STRING,"error");
menu_add_item(m,i);
menu_invoke((int)((TermWin_TotalWidth()-l)/2),(int)(TermWin_TotalHeight()/2)-20,TermWin.parent,m,CurrentTime);
do {
do {
while(!XPending(Xdisplay))
;
XNextEvent(Xdisplay,&ev);
} while(ev.type!=KeyPress);
len=XLookupString(&ev.xkey,(char *)kbuf,sizeof(short_buf),&keysym,NULL);
ch=kbuf[0];
l=strlen(b);
if(ch!='\t')
tab=0;
if(ch>=' ') {
if(l<maxlen) {
b[l+1]='\0';
b[l] =ch; }}
else if((ch=='\n')||(ch=='\r'))
f=1;
else if(ch=='\x08') {
if(maxlen&&l)
b[--l]='\0'; }
else if((ch=='\t')&&inp_tab) {
if(!tab)
tab=l;
inp_tab(xd,b,tab,maxlen); }
else if(ch=='\x1b')
f=2;
i->len=strlen(b);
menu_draw(m);
} while(!f);
i->text=old;
i->len =strlen(old);
/* we could just return b, but it might be longer than we need */
if(retstr)
*retstr=(!maxlen||(f==2))?NULL:strdup(b);
ret=(f==2)?-2:0;
}
m->font=NULL;
#ifdef MULTI_CHARSET
m->fontset=NULL;
#endif
menu_delete(m);
}
free(b);
return ret;
}

@ -34,6 +34,7 @@
#define MENUITEM_STRING (1UL << 2)
#define MENUITEM_ECHO (1UL << 3)
#define MENUITEM_SCRIPT (1UL << 4)
#define MENUITEM_ALERT (1UL << 5)
#define MENU_STATE_IS_MAPPED (1UL << 0)
#define MENU_STATE_IS_CURRENT (1UL << 1)
@ -63,6 +64,7 @@ typedef struct {
menu_t *submenu;
char *string;
char *script;
char *alert;
} action;
char *text, *rtext;
unsigned short len, rlen;
@ -92,6 +94,10 @@ typedef struct {
/************ Variables ************/
extern menulist_t *menu_list;
#ifdef ESCREEN
extern event_dispatcher_data_t menu_event_data;
#endif
/************ Function Prototypes ************/
_XFUNCPROTOBEGIN
@ -140,6 +146,8 @@ extern void menu_display(int, int, menu_t *);
extern void menu_action(menuitem_t *);
extern void menu_invoke(int, int, Window, menu_t *, Time);
extern void menu_invoke_by_title(int, int, Window, char *, Time);
extern int menu_tab(void *,char *[],int,char *,size_t,size_t);
extern int menu_dial(void *,char *, int, char **,int (*)(void *,char *,size_t,size_t));
_XFUNCPROTOEND

@ -138,6 +138,7 @@ char *rs_theme = NULL;
char *rs_config_file = NULL;
#ifdef ESCREEN
char *rs_url = NULL;
char *rs_hop = NULL;
#endif
unsigned int rs_line_space = 0;
unsigned int rs_meta_mod = 0, rs_alt_mod = 0, rs_numlock_mod = 0;
@ -166,6 +167,7 @@ static const struct {
OPT_STR('d', "display", "X server to connect to", &display_name),
#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),
#endif
#if DEBUG <= 0
OPT_ILONG("debug", "level of debugging information to show (support not compiled in)", &DEBUG_LEVEL),

@ -136,6 +136,7 @@ extern char *rs_theme;
extern char *rs_config_file;
#ifdef ESCREEN
extern char *rs_url;
extern char *rs_hop;
#endif
extern unsigned int rs_line_space;
extern unsigned int rs_meta_mod, rs_alt_mod, rs_numlock_mod;

@ -1066,7 +1066,7 @@ render_simage(simage_t *simg, Window win, unsigned short width, unsigned short h
XSetClipMask(Xdisplay, gc, mask);
XSetClipOrigin(Xdisplay, gc, 0, 0);
}
if (simg->pmap->pixmap) {
if (simg->pmap->pixmap != None) {
LIBAST_X_FREE_PIXMAP(simg->pmap->pixmap);
simg->pmap->pixmap = None;
}
@ -1275,7 +1275,7 @@ render_simage(simage_t *simg, Window win, unsigned short width, unsigned short h
XSetWindowBackgroundPixmap(Xdisplay, win, buffer_pixmap);
} else {
if ((renderop & RENDER_FORCE_PIXMAP) || (simg->iml->bevel != NULL)) {
if (simg->pmap->pixmap) {
if (simg->pmap->pixmap != None) {
LIBAST_X_FREE_PIXMAP(simg->pmap->pixmap);
}
simg->pmap->pixmap = LIBAST_X_CREATE_PIXMAP(width, height);
@ -2118,7 +2118,6 @@ get_desktop_pixmap(void)
void
free_desktop_pixmap(void)
{
if (desktop_pixmap_is_mine && desktop_pixmap != None) {
LIBAST_X_FREE_PIXMAP(desktop_pixmap);
desktop_pixmap_is_mine = 0;

@ -1,7 +1,7 @@
/****************************************************************************
* scream::scream.h
* routines to connect to screen and or scream daemons.
* GNU Public Licence applies.
* BSD Licence applies.
* 2002/04/19 Azundris incept
***************************************************************************/
@ -32,6 +32,7 @@
#define NS_SCREEN_STATUS 11
#define NS_SCREEN_ST_CLR 12
#define NS_EFUN_NOT_SET 13
#define NS_USER_CXL 14
#define NS_ERR_WEIRDSCREEN 1
@ -46,29 +47,51 @@
#define NS_SCREAM_MASK (~(NS_SCREAM_UTMP|NS_SCREAM_PRVS))
#define NS_HOP_DOWN 0
#define NS_HOP_UP 1
/***************************************************************************/
typedef struct __ns_sess { /* a whole screen-session with many clients */
int where; /* local/remote */
int backend; /* screen/scream */
int nesting; /* 0=topLevel, 1=screen within a screen etc */
char *proto; /* protocol. usually "screen" */
char *host; /* host. numeric or symbolic. often "localhost" */
int port; /* port. usually TCP22: SSH */
char *user; /* user. often current local user */
char *pass; /* password. used for su. for remote sessions, a
ssh-key should be placed on the remote machine. */
char *rsrc; /* additional parameter to screen/scream. URL-enc */
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 */
typedef struct __ns_hop {
int localport;
char *fw;
int fwport;
int established;
int delay;
int refcount;
struct __ns_sess *sess; /* first only, others have same host/port */
struct __ns_hop *next;
} _ns_hop;
typedef struct __ns_sess { /* a whole screen-session with many clients */
int where; /* local/remote */
int backend; /* screen/scream */
int nesting; /* 0=topLevel, 1=screen within a screen etc */
time_t timestamp; /* last updated when? see NS_SCREEN_UPD_FREQ */
char *proto; /* protocol. usually "screen" */
char *host; /* host. numeric or symbolic. ("localhost") */
int port; /* port. usually TCP22: SSH */
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 */
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 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 */
} _ns_sess;
@ -105,6 +128,8 @@ typedef struct __ns_efuns { /* callbacks into the terminal program */
int (*err_msg)(void *,int,char *);
int (*execute)(void *,char **);
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);
} _ns_efuns;
@ -128,6 +153,7 @@ _ns_efuns *ns_dst_efuns(_ns_efuns **);
_ns_efuns *ns_get_efuns(_ns_sess *,_ns_disp *);
/* debug */
void ns_desc_hop(_ns_hop *,char *);
void ns_desc_sess(_ns_sess *,char *);
/* convenience */
@ -135,11 +161,32 @@ _ns_disp *disp_fetch_or_make(_ns_sess *,int);
/* transparent attach/detach */
_ns_sess *ns_attach_by_sess(_ns_sess **,int *);
_ns_sess *ns_attach_by_URL(char *,_ns_efuns **,int *,void *);
_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 */
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-hotkey */
int ns_parse_screen_key(_ns_sess *,char);
/* parse screen escape setup */
char ns_parse_esc(char **);
/* init session (read .screenrc, or whatnot) */
int ns_sess_init(_ns_sess *);
/* what the terminal should call the last line -- screen's "hardstatus"
changes. submit session, terminal-width, and a pointer to said line. */
int parse_screen(_ns_sess *,int,int,char *);
int ns_parse_screen(_ns_sess *,int,int,char *);
/* things the term might ask screen/scream to do ***************************/
int ns_scroll2x(_ns_sess *,int);
@ -151,6 +198,9 @@ int ns_rem_disp(_ns_sess *,int);
int ns_ren_disp(_ns_sess *,int,char *);
int ns_log_disp(_ns_sess *,int,char *);