#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"
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)
{
/*
*/
}
+/*
+ * 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.
struct gui_data *inst = dctx->inst;
GdkGC *gc = dctx->gc;
- int nfg, nbg, t, fontid, shadow;
+ int nfg, nbg, t, fontid, shadow, rlen;
/*
* NYI:
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,
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)
{
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:
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);
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);
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);
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;
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;