X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/a832773496d46caa5e328d36a15b4918f24a804e..a86a2725f697fec44ea1527b8c11ff43798c9dfe:/unix/pterm.c diff --git a/unix/pterm.c b/unix/pterm.c index 0d18a7c9..22b9c2cd 100644 --- a/unix/pterm.c +++ b/unix/pterm.c @@ -16,10 +16,11 @@ #include #include #include -#include -#include #include #include +#include +#include +#include #define PUTTY_DO_GLOBALS /* actually _define_ globals */ #include "putty.h" @@ -50,6 +51,7 @@ struct gui_data { guint term_paste_idle_id; GdkAtom compound_text_atom; int alt_keycode; + int alt_digits; char wintitle[sizeof(((Config *)0)->wintitle)]; char icontitle[sizeof(((Config *)0)->wintitle)]; int master_fd, master_func_id, exited; @@ -67,6 +69,13 @@ struct draw_ctx { static int send_raw_mouse; +static char *app_name = "pterm"; + +char *x_get_default(char *key) +{ + return XGetDefault(GDK_DISPLAY(), app_name, key); +} + void ldisc_update(void *frontend, int echo, int edit) { /* @@ -354,11 +363,17 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) /* * If Alt is being released after typing an Alt+numberpad * sequence, we should generate the code that was typed. + * + * Note that we only do this if more than one key was actually + * pressed - I don't think Alt+NumPad4 should be ^D or that + * Alt+NumPad3 should be ^C, for example. There's no serious + * inconvenience in having to type a zero before a single-digit + * character code. */ if (event->type == GDK_KEY_RELEASE && (event->keyval == GDK_Meta_L || event->keyval == GDK_Alt_L || event->keyval == GDK_Meta_R || event->keyval == GDK_Alt_R) && - inst->alt_keycode >= 0) { + inst->alt_keycode >= 0 && inst->alt_digits > 1) { #ifdef KEY_DEBUGGING printf("Alt key up, keycode = %d\n", inst->alt_keycode); #endif @@ -391,6 +406,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) if ((event->keyval == GDK_Meta_L || event->keyval == GDK_Alt_L || event->keyval == GDK_Meta_R || event->keyval == GDK_Alt_R)) { inst->alt_keycode = -1; + inst->alt_digits = 0; goto done; /* this generates nothing else */ } @@ -425,6 +441,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) inst->alt_keycode = digit; /* one-digit code */ else inst->alt_keycode = inst->alt_keycode * 10 + digit; + inst->alt_digits++; #ifdef KEY_DEBUGGING printf(" gives new code %d\n", inst->alt_keycode); #endif @@ -1229,7 +1246,7 @@ void request_paste(void *frontend) gint idle_paste_func(gpointer data); /* forward ref */ void selection_received(GtkWidget *widget, GtkSelectionData *seldata, - gpointer data) + guint time, gpointer data) { struct gui_data *inst = (struct gui_data *)data; @@ -1323,12 +1340,19 @@ void sys_cursor(void *frontend, int x, int y) */ } +/* + * This is still called when mode==BELL_VISUAL, even though the + * visual bell is handled entirely within terminal.c, because we + * may want to perform additional actions on any kind of bell (for + * example, taskbar flashing in Windows). + */ void beep(void *frontend, int mode) { - gdk_beep(); + if (mode != BELL_VISUAL) + gdk_beep(); } -int CharWidth(Context ctx, int uc) +int char_width(Context ctx, int uc) { /* * Under X, any fixed-width font really _is_ fixed-width. @@ -1374,7 +1398,7 @@ void do_text_internal(Context ctx, int x, int y, char *text, int len, struct gui_data *inst = dctx->inst; GdkGC *gc = dctx->gc; - int nfg, nbg, t, fontid, shadow; + int nfg, nbg, t, fontid, shadow, rlen; /* * NYI: @@ -1411,13 +1435,25 @@ void do_text_internal(Context ctx, int x, int y, char *text, int len, return; if (x + len*2 > inst->term->cols) len = (inst->term->cols-x)/2; /* trim to LH half */ + rlen = len * 2; + } else + rlen = len; + + { + GdkRectangle r; + + r.x = x*inst->font_width+cfg.window_border; + r.y = y*inst->font_height+cfg.window_border; + r.width = rlen*inst->font_width; + r.height = inst->font_height; + gdk_gc_set_clip_rectangle(gc, &r); } gdk_gc_set_foreground(gc, &inst->cols[nbg]); gdk_draw_rectangle(inst->pixmap, gc, 1, x*inst->font_width+cfg.window_border, y*inst->font_height+cfg.window_border, - len*inst->font_width, inst->font_height); + rlen*inst->font_width, inst->font_height); gdk_gc_set_foreground(gc, &inst->cols[nfg]); gdk_draw_text(inst->pixmap, inst->fonts[fontid], gc, @@ -1710,7 +1746,32 @@ char *get_x_display(void *frontend) return gdk_get_display(); } -char *app_name = "pterm"; +static void help(FILE *fp) { + if(fprintf(fp, +"pterm option summary:\n" +"\n" +" --display DISPLAY Specify X display to use (note '--')\n" +" -name PREFIX Prefix when looking up resources (default: pterm)\n" +" -fn FONT Normal text font\n" +" -fb FONT Bold text font\n" +" -geometry WIDTHxHEIGHT Size of terminal in characters\n" +" -sl LINES Number of lines of scrollback\n" +" -fg COLOUR, -bg COLOUR Foreground/background colour\n" +" -bfg COLOUR, -bbg COLOUR Foreground/background bold colour\n" +" -cfg COLOUR, -bfg COLOUR Foreground/background cursor colour\n" +" -T TITLE Window title\n" +" -ut, +ut Do(default) or do not update utmp\n" +" -ls, +ls Do(default) or do not make shell a login shell\n" +" -sb, +sb Do(default) or do not display a scrollbar\n" +" -log PATH Log all output to a file\n" +" -nethack Map numeric keypad to hjklyubn direction keys\n" +" -xrm RESOURCE-STRING Set an X resource\n" +" -e COMMAND [ARGS...] Execute command (consumes all remaining args)\n" + ) < 0 || fflush(fp) < 0) { + perror("output error"); + exit(1); + } +} int do_cmdline(int argc, char **argv, int do_everything) { @@ -1718,18 +1779,22 @@ int do_cmdline(int argc, char **argv, int do_everything) extern char **pty_argv; /* declared in pty.c */ /* - * Macros to make argument handling easier. + * Macros to make argument handling easier. Note that because + * they need to call `continue', they cannot be contained in + * the usual do {...} while (0) wrapper to make them + * syntactically single statements; hence it is not legal to + * use one of these macros as an unbraced statement between + * `if' and `else'. */ -#define EXPECTS_ARG do { \ +#define EXPECTS_ARG { \ if (--argc <= 0) { \ err = 1; \ fprintf(stderr, "pterm: %s expects an argument\n", p); \ + continue; \ } else \ val = *++argv; \ -} while (0) -#define SECOND_PASS_ONLY do { \ - if (!do_everything) continue; \ -} while (0) +} +#define SECOND_PASS_ONLY { if (!do_everything) continue; } /* * TODO: @@ -1865,6 +1930,10 @@ int do_cmdline(int argc, char **argv, int do_everything) EXPECTS_ARG; provide_xrm_string(val); + } else if(!strcmp(p, "-help") || !strcmp(p, "--help")) { + help(stdout); + exit(0); + } else { err = 1; fprintf(stderr, "pterm: unrecognized option '%s'\n", p); @@ -1874,12 +1943,27 @@ int do_cmdline(int argc, char **argv, int do_everything) return err; } +static void block_signal(int sig, int block_it) { + sigset_t ss; + + sigemptyset(&ss); + sigaddset(&ss, sig); + if(sigprocmask(block_it ? SIG_BLOCK : SIG_UNBLOCK, &ss, 0) < 0) { + perror("sigprocmask"); + exit(1); + } +} + int main(int argc, char **argv) { extern int pty_master_fd; /* declared in pty.c */ extern void pty_pre_init(void); /* declared in pty.c */ struct gui_data *inst; + /* defer any child exit handling until we're ready to deal with + * it */ + block_signal(SIGCHLD, 1); + pty_pre_init(); gtk_init(&argc, &argv); @@ -1895,6 +1979,7 @@ int main(int argc, char **argv) */ inst = smalloc(sizeof(*inst)); memset(inst, 0, sizeof(*inst)); + inst->alt_keycode = -1; /* this one needs _not_ to be zero */ inst->fonts[0] = gdk_font_load(cfg.font); if (!inst->fonts[0]) { @@ -2016,7 +2101,7 @@ int main(int argc, char **argv) inst->currcursor = inst->textcursor; show_mouseptr(inst, 1); - inst->term = term_init(inst); + inst->term = term_init(&cfg, inst); inst->logctx = log_init(inst); term_provide_logctx(inst->term, inst->logctx); @@ -2028,7 +2113,8 @@ int main(int argc, char **argv) term_size(inst->term, cfg.height, cfg.width, cfg.savelines); - inst->ldisc = ldisc_create(inst->term, inst->back, inst->backhandle, inst); + inst->ldisc = + ldisc_create(&cfg, inst->term, inst->back, inst->backhandle, inst); ldisc_send(inst->ldisc, NULL, 0, 0);/* cause ldisc to notice changes */ inst->master_fd = pty_master_fd; @@ -2036,6 +2122,10 @@ int main(int argc, char **argv) inst->master_func_id = gdk_input_add(pty_master_fd, GDK_INPUT_READ, pty_input_func, inst); + /* now we're reday to deal with the child exit handler being + * called */ + block_signal(SIGCHLD, 0); + gtk_main(); return 0;