Improve shadow bold mode: set the default shadow bold offset to +1
[u/mdw/putty] / unix / pterm.c
index 0d18a7c..b1b98c1 100644 (file)
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/wait.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
 #include <gtk/gtk.h>
 #include <gdk/gdkkeysyms.h>
+#include <gdk/gdkx.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
 
 #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,9 +1340,16 @@ 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)
@@ -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)
 {
@@ -1865,6 +1926,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 +1939,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 +1975,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]) {
@@ -2036,6 +2117,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;