GtkWidget *window, *area, *sbar;
GtkBox *hbox;
GtkAdjustment *sbar_adjust;
+ GtkWidget *menu, *specialsmenu, *specialsitem1, *specialsitem2;
GdkPixmap *pixmap;
GdkFont *fonts[4]; /* normal, bold, wide, widebold */
struct {
return XGetDefault(GDK_DISPLAY(), app_name, key);
}
+void connection_fatal(void *frontend, char *p, ...)
+{
+ Terminal *term = (Terminal *)frontend;
+ struct gui_data *inst = (struct gui_data *)term->frontend;
+
+ va_list ap;
+ char *msg;
+ va_start(ap, p);
+ msg = dupvprintf(p, ap);
+ va_end(ap);
+ inst->exited = TRUE;
+ fatal_message_box(inst->window, msg);
+ sfree(msg);
+ if (inst->cfg.close_on_exit == FORCE_ON)
+ cleanup_exit(1);
+}
+
/*
* Default settings that are specific to pterm.
*/
shift = event->state & GDK_SHIFT_MASK;
ctrl = event->state & GDK_CONTROL_MASK;
alt = event->state & GDK_MOD1_MASK;
+
+ if (event->button == 3 && ctrl) {
+ gtk_menu_popup(GTK_MENU(inst->menu), NULL, NULL, NULL, NULL,
+ event->button, event->time);
+ return TRUE;
+ }
+
if (event->button == 1)
button = MBT_LEFT;
else if (event->button == 2)
struct gui_data *inst = (struct gui_data *)data;
int exitcode;
- if ((exitcode = inst->back->exitcode(inst->backhandle)) >= 0) {
+ if (!inst->exited &&
+ (exitcode = inst->back->exitcode(inst->backhandle)) >= 0) {
inst->exited = TRUE;
if (inst->cfg.close_on_exit == FORCE_ON ||
(inst->cfg.close_on_exit == AUTO && exitcode == 0))
void fd_input_func(gpointer data, gint sourcefd, GdkInputCondition condition)
{
- select_result(sourcefd,
- (condition == GDK_INPUT_READ ? 1 :
- condition == GDK_INPUT_WRITE ? 2 :
- condition == GDK_INPUT_EXCEPTION ? 4 : -1));
+ /*
+ * We must process exceptional notifications before ordinary
+ * readability ones, or we may go straight past the urgent
+ * marker.
+ */
+ if (condition & GDK_INPUT_EXCEPTION)
+ select_result(sourcefd, 4);
+ if (condition & GDK_INPUT_READ)
+ select_result(sourcefd, 1);
+ if (condition & GDK_INPUT_WRITE)
+ select_result(sourcefd, 2);
}
void destroy(GtkWidget *widget, gpointer data)
exit(1);
}
+void cmdline_error(char *p, ...)
+{
+ va_list ap;
+ fprintf(stderr, "plink: ");
+ va_start(ap, p);
+ vfprintf(stderr, p, ap);
+ va_end(ap);
+ fputc('\n', stderr);
+ exit(1);
+}
+
char *get_x_display(void *frontend)
{
return gdk_get_display();
char *val;
while (--argc > 0) {
char *p = *++argv;
+ int ret;
+
+ ret = cmdline_process_param(p, (argc > 1 ? argv[1] : NULL),
+ do_everything ? 1 : -1, cfg);
+
+ if (ret == -2) {
+ cmdline_error("option \"%s\" requires an argument", p);
+ } else if (ret == 2) {
+ --argc, ++argv; /* skip next argument */
+ continue;
+ } else if (ret == 1) {
+ continue;
+ }
+
if (!strcmp(p, "-fn") || !strcmp(p, "-font")) {
EXPECTS_ARG;
SECOND_PASS_ONLY;
help(stdout);
exit(0);
+ } else if(p[0] != '-' && (!do_everything ||
+ process_nonoption_arg(p, cfg))) {
+ /* do nothing */
+
} else {
err = 1;
fprintf(stderr, "pterm: unrecognized option '%s'\n", p);
gdk_input_remove(id);
}
+void clear_scrollback_menuitem(GtkMenuItem *item, gpointer data)
+{
+ struct gui_data *inst = (struct gui_data *)data;
+ term_clrsb(inst->term);
+}
+
+void reset_terminal_menuitem(GtkMenuItem *item, gpointer data)
+{
+ struct gui_data *inst = (struct gui_data *)data;
+ term_pwron(inst->term);
+ ldisc_send(inst->ldisc, NULL, 0, 0);
+}
+
+void special_menuitem(GtkMenuItem *item, gpointer data)
+{
+ struct gui_data *inst = (struct gui_data *)data;
+ int code = (int)gtk_object_get_data(GTK_OBJECT(item), "user-data");
+
+ inst->back->special(inst->backhandle, code);
+}
+
+void about_menuitem(GtkMenuItem *item, gpointer data)
+{
+ /* struct gui_data *inst = (struct gui_data *)data; */
+ about_box();
+}
+
+void update_specials_menu(void *frontend)
+{
+ Terminal *term = (Terminal *)frontend;
+ struct gui_data *inst = (struct gui_data *)term->frontend;
+
+ const struct telnet_special *specials;
+
+ specials = inst->back->get_specials(inst->backhandle);
+ gtk_container_foreach(GTK_CONTAINER(inst->specialsmenu),
+ (GtkCallback)gtk_widget_destroy, NULL);
+ if (specials) {
+ int i;
+ GtkWidget *menuitem;
+ for (i = 0; specials[i].name; i++) {
+ if (*specials[i].name) {
+ menuitem = gtk_menu_item_new_with_label(specials[i].name);
+ gtk_object_set_data(GTK_OBJECT(menuitem), "user-data",
+ (gpointer)specials[i].code);
+ gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
+ GTK_SIGNAL_FUNC(special_menuitem), inst);
+ } else
+ menuitem = gtk_menu_item_new();
+ gtk_container_add(GTK_CONTAINER(inst->specialsmenu), menuitem);
+ gtk_widget_show(menuitem);
+ }
+ gtk_widget_show(inst->specialsitem1);
+ gtk_widget_show(inst->specialsitem2);
+ } else {
+ gtk_widget_hide(inst->specialsitem1);
+ gtk_widget_hide(inst->specialsitem2);
+ }
+}
+
int pt_main(int argc, char **argv)
{
extern Backend *select_backend(Config *cfg);
if (do_cmdline(argc, argv, 1, &inst->cfg))
exit(1); /* post-defaults, do everything */
- if (!cfgbox(&inst->cfg))
+ cmdline_run_saved(&inst->cfg);
+
+ if (!*inst->cfg.host && !cfgbox(&inst->cfg))
exit(0); /* config box hit Cancel */
inst->fonts[0] = gdk_font_load(inst->cfg.font.name);
set_window_background(inst);
+ /*
+ * Set up the Ctrl+rightclick context menu.
+ */
+ {
+ GtkWidget *menuitem;
+ char *s;
+
+ inst->menu = gtk_menu_new();
+
+#define MKMENUITEM(title, func) do { \
+ menuitem = title ? gtk_menu_item_new_with_label(title) : \
+ gtk_menu_item_new(); \
+ gtk_container_add(GTK_CONTAINER(inst->menu), menuitem); \
+ gtk_widget_show(menuitem); \
+ if (func != NULL) \
+ gtk_signal_connect(GTK_OBJECT(menuitem), "activate", \
+ GTK_SIGNAL_FUNC(func), inst); \
+} while (0)
+ MKMENUITEM("Special Commands", NULL);
+ inst->specialsmenu = gtk_menu_new();
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), inst->specialsmenu);
+ inst->specialsitem1 = menuitem;
+ MKMENUITEM(NULL, NULL);
+ inst->specialsitem2 = menuitem;
+ MKMENUITEM("Clear Scrollback", clear_scrollback_menuitem);
+ MKMENUITEM("Reset Terminal", reset_terminal_menuitem);
+ MKMENUITEM(NULL, NULL);
+ s = dupcat("About ", appname, NULL);
+ MKMENUITEM(s, about_menuitem);
+ sfree(s);
+#undef MKMENUITEM
+ }
+
inst->textcursor = make_mouse_ptr(inst, GDK_XTERM);
inst->rawcursor = make_mouse_ptr(inst, GDK_LEFT_PTR);
inst->blankcursor = make_mouse_ptr(inst, -1);
uxsel_init();
+ term_size(inst->term, inst->cfg.height, inst->cfg.width, inst->cfg.savelines);
+
inst->back = select_backend(&inst->cfg);
{
- char *realhost;
-
- inst->back->init((void *)inst->term, &inst->backhandle, &inst->cfg,
- inst->cfg.host, inst->cfg.port, &realhost,
- inst->cfg.tcp_nodelay);
+ char *realhost, *error;
+
+ error = inst->back->init((void *)inst->term, &inst->backhandle,
+ &inst->cfg, inst->cfg.host, inst->cfg.port,
+ &realhost, inst->cfg.tcp_nodelay);
+
+ if (error) {
+ char *msg = dupprintf("Unable to open connection to %s:\n%s",
+ inst->cfg.host, error);
+ inst->exited = TRUE;
+ fatal_message_box(inst->window, msg);
+ sfree(msg);
+ return 0;
+ }
if (inst->cfg.wintitle[0])
set_title(inst, inst->cfg.wintitle);
}
}
inst->back->provide_logctx(inst->backhandle, inst->logctx);
+ update_specials_menu(inst->term);
term_provide_resize_fn(inst->term, inst->back->size, inst->backhandle);
- term_size(inst->term, inst->cfg.height, inst->cfg.width, inst->cfg.savelines);
-
inst->ldisc =
ldisc_create(&inst->cfg, inst->term, inst->back, inst->backhandle, inst);
ldisc_send(inst->ldisc, NULL, 0, 0);/* cause ldisc to notice changes */