1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 17:38:00 +00:00

Ctrl+rightclick now pops up a context menu in Unix PuTTY and pterm.

This menu is not yet fully populated, but it has an About box (yet
another licence location :-/ ) and supports the new configurable
specials menu (thus making Unix PuTTY do one tiny thing which
OpenSSH-in-a-pterm can't :-).

[originally from svn r3062]
This commit is contained in:
Simon Tatham 2003-04-05 16:05:00 +00:00
parent f9f5154e76
commit 30497ff683
9 changed files with 258 additions and 28 deletions

View File

@ -25,6 +25,9 @@ The resource files:
+ the copyright date appears twice, once in the About box and
once in the Licence box. Don't forget to change both!
- putty/mac/mac_res.r
- putty/unix/gtkdlg.c
+ the copyright date appears twice, once in the About box and
once in the Licence box. Don't forget to change both!
The documentation (both the preamble blurb and the licence appendix):
@ -34,7 +37,7 @@ The documentation (both the preamble blurb and the licence appendix):
The website:
- putty-website/licence.html
Before tagging a release
------------------------

2
Recipe
View File

@ -154,7 +154,7 @@ puttygen : [G] puttygen sshrsag sshdssg sshprime sshdes sshbn sshmd5 version
pterm : [X] pterm terminal wcwidth uxucs uxmisc tree234 misc ldisc ldiscucs
+ logging uxprint settings pty uxsel be_none uxstore signal CHARSET
+ cmdline ptermm
+ cmdline ptermm UXCFG version
putty : [X] pterm terminal wcwidth uxucs uxmisc tree234 misc ldisc ldiscucs
+ logging uxprint settings pty uxsel be_all uxstore signal CHARSET
+ uxputty NONSSH UXSSH UXMISC logging ux_x11 UXCFG

View File

@ -304,6 +304,12 @@ extern struct backend_list {
*/
extern const int be_default_protocol;
/*
* Name of this particular application, for use in the config box
* and other pieces of text.
*/
extern const char *const appname;
/*
* IMPORTANT POLICY POINT: everything in this structure which wants
* to be treated like an integer must be an actual, honest-to-

View File

@ -2355,3 +2355,104 @@ void fatalbox(char *p, ...)
sfree(msg);
cleanup_exit(1);
}
static GtkWidget *aboutbox = NULL;
static void about_close_clicked(GtkButton *button, gpointer data)
{
gtk_widget_destroy(aboutbox);
aboutbox = NULL;
}
static void licence_clicked(GtkButton *button, gpointer data)
{
char *title;
char *licence =
"Copyright 1997-2003 Simon Tatham.\n\n"
"Portions copyright Robert de Bath, Joris van Rantwijk, Delian "
"Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas "
"Barry, Justin Bradford, Ben Harris, and CORE SDI S.A.\n\n"
"Permission is hereby granted, free of charge, to any person "
"obtaining a copy of this software and associated documentation "
"files (the ""Software""), to deal in the Software without restriction, "
"including without limitation the rights to use, copy, modify, merge, "
"publish, distribute, sublicense, and/or sell copies of the Software, "
"and to permit persons to whom the Software is furnished to do so, "
"subject to the following conditions:\n\n"
"The above copyright notice and this permission notice shall be "
"included in all copies or substantial portions of the Software.\n\n"
"THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT "
"WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, "
"INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF "
"MERCHANTABILITY, FITNESS FOR A PARTICULAR "
"PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE "
"COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES "
"OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, "
"TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN "
"CONNECTION WITH THE SOFTWARE OR THE USE OR "
"OTHER DEALINGS IN THE SOFTWARE.";
title = dupcat(appname, " Licence", NULL);
assert(aboutbox != NULL);
messagebox(aboutbox, title, licence,
string_width("LONGISH LINE OF TEXT SO THE LICENCE"
" BOX ISN'T EXCESSIVELY TALL AND THIN"),
"OK", 'o', 1, 1, NULL);
sfree(title);
}
void about_box(void)
{
GtkWidget *w;
char *title;
if (aboutbox) {
gtk_widget_grab_focus(aboutbox);
return;
}
aboutbox = gtk_dialog_new();
gtk_container_set_border_width(GTK_CONTAINER(aboutbox), 10);
title = dupcat("About ", appname, NULL);
gtk_window_set_title(GTK_WINDOW(aboutbox), title);
sfree(title);
w = gtk_button_new_with_label("Close");
GTK_WIDGET_SET_FLAGS(w, GTK_CAN_DEFAULT);
gtk_window_set_default(GTK_WINDOW(aboutbox), w);
gtk_box_pack_end(GTK_BOX(GTK_DIALOG(aboutbox)->action_area),
w, FALSE, FALSE, 0);
gtk_signal_connect(GTK_OBJECT(w), "clicked",
GTK_SIGNAL_FUNC(about_close_clicked), NULL);
gtk_widget_show(w);
w = gtk_button_new_with_label("View Licence");
GTK_WIDGET_SET_FLAGS(w, GTK_CAN_DEFAULT);
gtk_box_pack_end(GTK_BOX(GTK_DIALOG(aboutbox)->action_area),
w, FALSE, FALSE, 0);
gtk_signal_connect(GTK_OBJECT(w), "clicked",
GTK_SIGNAL_FUNC(licence_clicked), NULL);
gtk_widget_show(w);
w = gtk_label_new(appname);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(aboutbox)->vbox),
w, FALSE, FALSE, 0);
gtk_widget_show(w);
w = gtk_label_new(ver);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(aboutbox)->vbox),
w, FALSE, FALSE, 5);
gtk_widget_show(w);
w = gtk_label_new("Copyright 1997-2003 Simon Tatham. All rights reserved");
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(aboutbox)->vbox),
w, FALSE, FALSE, 5);
gtk_widget_show(w);
gtk_widget_show(aboutbox);
}

View File

@ -38,6 +38,7 @@ struct gui_data {
GtkWidget *window, *area, *sbar;
GtkBox *hbox;
GtkAdjustment *sbar_adjust;
GtkWidget *menu, *specialsmenu, *specialsitem1, *specialsitem2;
GdkPixmap *pixmap;
GdkFont *fonts[4]; /* normal, bold, wide, widebold */
struct {
@ -148,14 +149,6 @@ void ldisc_update(void *frontend, int echo, int edit)
*/
}
void update_specials_menu(void *frontend)
{
/*
* When I implement a context menu in pterm, I will need to
* support this function properly.
*/
}
int askappend(void *frontend, Filename filename)
{
/*
@ -968,6 +961,13 @@ gint button_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
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)
@ -2293,6 +2293,66 @@ void uxsel_input_remove(int id) {
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);
@ -2457,6 +2517,39 @@ int pt_main(int argc, char **argv)
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);
@ -2498,6 +2591,7 @@ int pt_main(int argc, char **argv)
}
}
inst->back->provide_logctx(inst->backhandle, inst->logctx);
update_specials_menu(inst->term);
term_provide_resize_fn(inst->term, inst->back->size, inst->backhandle);

View File

@ -7,6 +7,37 @@
#include "putty.h"
const char *const appname = "pterm";
/*
* Another bunch of temporary stub functions. These ones will want
* removing by means of implementing them properly: libcharset
* should invent its own sensible format for codepage names and a
* means of enumerating them, and printer_enum needs to be dealt
* with somehow or other too.
*/
char *cp_name(int codepage)
{
return "";
}
char *cp_enumerate(int index)
{
return NULL;
}
int decode_codepage(char *cp_name)
{
return -2;
}
printer_enum *printer_start_enum(int *nprinters_ptr) {
*nprinters_ptr = 0;
return NULL;
}
char *printer_get_name(printer_enum *pe, int i) { return NULL;
}
void printer_finish_enum(printer_enum *pe) { }
Backend *select_backend(Config *cfg)
{
return &pty_backend;
@ -17,11 +48,6 @@ int cfgbox(Config *cfg)
return 1; /* no-op in pterm */
}
void fatal_message_box(void *window, char *msg)
{
/* also a no-op in pterm */
}
void cleanup_exit(int code)
{
exit(code);

View File

@ -60,6 +60,7 @@ void *get_window(void *frontend); /* void * to avoid depending on gtk.h */
/* Things pterm.c needs from gtkdlg.c */
void fatal_message_box(void *window, char *msg);
void about_box(void);
/* Things pterm.c needs from {ptermm,uxputty}.c */
char *make_default_wintitle(char *hostname);

View File

@ -10,23 +10,29 @@
#include "dialog.h"
#include "storage.h"
static void about_handler(union control *ctrl, void *dlg,
void *data, int event)
{
if (event == EVENT_ACTION) {
about_box();
}
}
void unix_setup_config_box(struct controlbox *b, int midsession)
{
struct controlset *s, *s2;
union control *c;
int i;
#ifdef FIXME
if (!midsession) {
/*
* Add the About button to the standard panel.
*/
s = ctrl_getset(b, "", "", "");
c = ctrl_pushbutton(s, "About", 'a', HELPCTX(no_help),
about_handler, P(hwndp));
about_handler, P(NULL));
c->generic.column = 0;
}
#endif
/*
* The Config structure contains two Unix-specific elements

View File

@ -20,12 +20,7 @@
* have uxcfg.c remove the drop-down list completely, since you
* can't sensibly provide an enumerated list of lpr commands!).
*
* - Ctrl+right-click for a context menu (also in Windows for
* consistency, I think). This should contain pretty much
* everything in the Windows PuTTY menu, and a subset of that in
* pterm:
*
* - Telnet special commands (not in pterm :-)
* - Remainder of the context menu:
*
* - Event Log (this means we must implement the Event Log; not
* in pterm)
@ -63,10 +58,6 @@
* to get hold of the application name.
*
* - Copy All to Clipboard (for what that's worth)
*
* - Clear Scrollback and Reset Terminal
*
* - About (and uxcfg.c must also supply the about box)
*/
/*
@ -111,6 +102,8 @@ char *printer_get_name(printer_enum *pe, int i) { return NULL;
}
void printer_finish_enum(printer_enum *pe) { }
const char *const appname = "PuTTY";
Backend *select_backend(Config *cfg)
{
int i;