📄 config.c
字号:
/* * config.c - the platform-independent parts of the PuTTY * configuration box. */#include <assert.h>#include <stdlib.h>#include "putty.h"#include "dialog.h"#include "storage.h"#define PRINTER_DISABLED_STRING "None (printing disabled)"static void protocolbuttons_handler(union control *ctrl, void *dlg, void *data, int event){ int button, defport; Config *cfg = (Config *)data; /* * This function works just like the standard radio-button * handler, except that it also has to change the setting of * the port box. We expect the context parameter to point at * the `union control' structure for the port box. */ if (event == EVENT_REFRESH) { for (button = 0; button < ctrl->radio.nbuttons; button++) if (cfg->protocol == ctrl->radio.buttondata[button].i) break; /* We expected that `break' to happen, in all circumstances. */ assert(button < ctrl->radio.nbuttons); dlg_radiobutton_set(ctrl, dlg, button); } else if (event == EVENT_VALCHANGE) { int oldproto = cfg->protocol; button = dlg_radiobutton_get(ctrl, dlg); assert(button >= 0 && button < ctrl->radio.nbuttons); cfg->protocol = ctrl->radio.buttondata[button].i; if (oldproto != cfg->protocol) { defport = -1; switch (cfg->protocol) { case PROT_SSH: defport = 22; break; case PROT_TELNET: defport = 23; break; case PROT_RLOGIN: defport = 513; break; } if (defport > 0 && cfg->port != defport) { cfg->port = defport; dlg_refresh((union control *)ctrl->radio.context.p, dlg); } } }}static void numeric_keypad_handler(union control *ctrl, void *dlg, void *data, int event){ int button; Config *cfg = (Config *)data; /* * This function works much like the standard radio button * handler, but it has to handle two fields in Config. */ if (event == EVENT_REFRESH) { if (cfg->nethack_keypad) button = 2; else if (cfg->app_keypad) button = 1; else button = 0; assert(button < ctrl->radio.nbuttons); dlg_radiobutton_set(ctrl, dlg, button); } else if (event == EVENT_VALCHANGE) { button = dlg_radiobutton_get(ctrl, dlg); assert(button >= 0 && button < ctrl->radio.nbuttons); if (button == 2) { cfg->app_keypad = FALSE; cfg->nethack_keypad = TRUE; } else { cfg->app_keypad = (button != 0); cfg->nethack_keypad = FALSE; } }}static void cipherlist_handler(union control *ctrl, void *dlg, void *data, int event){ Config *cfg = (Config *)data; if (event == EVENT_REFRESH) { int i; static const struct { char *s; int c; } ciphers[] = { { "3DES", CIPHER_3DES }, { "Blowfish", CIPHER_BLOWFISH }, { "DES", CIPHER_DES }, { "AES (SSH 2 only)", CIPHER_AES }, { "-- warn below here --", CIPHER_WARN } }; /* Set up the "selected ciphers" box. */ /* (cipherlist assumed to contain all ciphers) */ dlg_update_start(ctrl, dlg); dlg_listbox_clear(ctrl, dlg); for (i = 0; i < CIPHER_MAX; i++) { int c = cfg->ssh_cipherlist[i]; int j; char *cstr = NULL; for (j = 0; j < (sizeof ciphers) / (sizeof ciphers[0]); j++) { if (ciphers[j].c == c) { cstr = ciphers[j].s; break; } } dlg_listbox_addwithid(ctrl, dlg, cstr, c); } dlg_update_done(ctrl, dlg); } else if (event == EVENT_VALCHANGE) { int i; /* Update array to match the list box. */ for (i=0; i < CIPHER_MAX; i++) cfg->ssh_cipherlist[i] = dlg_listbox_getid(ctrl, dlg, i); }}static void printerbox_handler(union control *ctrl, void *dlg, void *data, int event){ Config *cfg = (Config *)data; if (event == EVENT_REFRESH) { int nprinters, i; printer_enum *pe; dlg_update_start(ctrl, dlg); /* * Some backends may wish to disable the drop-down list on * this edit box. Be prepared for this. */ if (ctrl->editbox.has_list) { dlg_listbox_clear(ctrl, dlg); dlg_listbox_add(ctrl, dlg, PRINTER_DISABLED_STRING); pe = printer_start_enum(&nprinters); for (i = 0; i < nprinters; i++) dlg_listbox_add(ctrl, dlg, printer_get_name(pe, i)); printer_finish_enum(pe); } dlg_editbox_set(ctrl, dlg, (*cfg->printer ? cfg->printer : PRINTER_DISABLED_STRING)); dlg_update_done(ctrl, dlg); } else if (event == EVENT_VALCHANGE) { dlg_editbox_get(ctrl, dlg, cfg->printer, sizeof(cfg->printer)); if (!strcmp(cfg->printer, PRINTER_DISABLED_STRING)) *cfg->printer = '\0'; }}static void codepage_handler(union control *ctrl, void *dlg, void *data, int event){ Config *cfg = (Config *)data; if (event == EVENT_REFRESH) { int i; const char *cp; dlg_update_start(ctrl, dlg); strcpy(cfg->line_codepage, cp_name(decode_codepage(cfg->line_codepage))); dlg_listbox_clear(ctrl, dlg); for (i = 0; (cp = cp_enumerate(i)) != NULL; i++) dlg_listbox_add(ctrl, dlg, cp); dlg_editbox_set(ctrl, dlg, cfg->line_codepage); dlg_update_done(ctrl, dlg); } else if (event == EVENT_VALCHANGE) { dlg_editbox_get(ctrl, dlg, cfg->line_codepage, sizeof(cfg->line_codepage)); strcpy(cfg->line_codepage, cp_name(decode_codepage(cfg->line_codepage))); }}static void sshbug_handler(union control *ctrl, void *dlg, void *data, int event){ if (event == EVENT_REFRESH) { dlg_update_start(ctrl, dlg); dlg_listbox_clear(ctrl, dlg); dlg_listbox_addwithid(ctrl, dlg, "Auto", AUTO); dlg_listbox_addwithid(ctrl, dlg, "Off", FORCE_OFF); dlg_listbox_addwithid(ctrl, dlg, "On", FORCE_ON); switch (*(int *)ATOFFSET(data, ctrl->listbox.context.i)) { case AUTO: dlg_listbox_select(ctrl, dlg, 0); break; case FORCE_OFF: dlg_listbox_select(ctrl, dlg, 1); break; case FORCE_ON: dlg_listbox_select(ctrl, dlg, 2); break; } dlg_update_done(ctrl, dlg); } else if (event == EVENT_SELCHANGE) { int i = dlg_listbox_index(ctrl, dlg); if (i < 0) i = AUTO; else i = dlg_listbox_getid(ctrl, dlg, i); *(int *)ATOFFSET(data, ctrl->listbox.context.i) = i; }}#define SAVEDSESSION_LEN 2048struct sessionsaver_data { union control *editbox, *listbox, *loadbutton, *savebutton, *delbutton; union control *okbutton, *cancelbutton; struct sesslist *sesslist;};/* * Helper function to load the session selected in the list box, if * any, as this is done in more than one place below. Returns 0 for * failure. */static int load_selected_session(struct sessionsaver_data *ssd, char *savedsession, void *dlg, Config *cfg){ int i = dlg_listbox_index(ssd->listbox, dlg); int isdef; if (i < 0) { dlg_beep(dlg); return 0; } isdef = !strcmp(ssd->sesslist->sessions[i], "Default Settings"); load_settings(ssd->sesslist->sessions[i], !isdef, cfg); if (!isdef) { strncpy(savedsession, ssd->sesslist->sessions[i], SAVEDSESSION_LEN); savedsession[SAVEDSESSION_LEN-1] = '\0'; } else { savedsession[0] = '\0'; } dlg_refresh(NULL, dlg); /* Restore the selection, which might have been clobbered by * changing the value of the edit box. */ dlg_listbox_select(ssd->listbox, dlg, i); return 1;}static void sessionsaver_handler(union control *ctrl, void *dlg, void *data, int event){ Config *cfg = (Config *)data; struct sessionsaver_data *ssd = (struct sessionsaver_data *)ctrl->generic.context.p; char *savedsession; /* * The first time we're called in a new dialog, we must * allocate space to store the current contents of the saved * session edit box (since it must persist even when we switch * panels, but is not part of the Config). * * Of course, this doesn't need to be done mid-session. */ if (!ssd->editbox) { savedsession = NULL; } else if (!dlg_get_privdata(ssd->editbox, dlg)) { savedsession = (char *) dlg_alloc_privdata(ssd->editbox, dlg, SAVEDSESSION_LEN); savedsession[0] = '\0'; } else { savedsession = dlg_get_privdata(ssd->editbox, dlg); } if (event == EVENT_REFRESH) { if (ctrl == ssd->editbox) { dlg_editbox_set(ctrl, dlg, savedsession); } else if (ctrl == ssd->listbox) { int i; dlg_update_start(ctrl, dlg); dlg_listbox_clear(ctrl, dlg); for (i = 0; i < ssd->sesslist->nsessions; i++) dlg_listbox_add(ctrl, dlg, ssd->sesslist->sessions[i]); dlg_update_done(ctrl, dlg); } } else if (event == EVENT_VALCHANGE) { if (ctrl == ssd->editbox) { dlg_editbox_get(ctrl, dlg, savedsession, SAVEDSESSION_LEN); } } else if (event == EVENT_ACTION) { if (ctrl == ssd->listbox || ctrl == ssd->loadbutton) { /* * The user has double-clicked a session, or hit Load. * We must load the selected session, and then * terminate the configuration dialog _if_ there was a * double-click on the list box _and_ that session * contains a hostname. */ if (load_selected_session(ssd, savedsession, dlg, cfg) && (ctrl == ssd->listbox && cfg->host[0])) { dlg_end(dlg, 1); /* it's all over, and succeeded */ } } else if (ctrl == ssd->savebutton) { int isdef = !strcmp(savedsession, "Default Settings"); if (!savedsession[0]) { int i = dlg_listbox_index(ssd->listbox, dlg); if (i < 0) { dlg_beep(dlg); return; } isdef = !strcmp(ssd->sesslist->sessions[i], "Default Settings"); if (!isdef) { strncpy(savedsession, ssd->sesslist->sessions[i], SAVEDSESSION_LEN); savedsession[SAVEDSESSION_LEN-1] = '\0'; } else { savedsession[0] = '\0'; } } { char *errmsg = save_settings(savedsession, !isdef, cfg); if (errmsg) { dlg_error_msg(dlg, errmsg); sfree(errmsg); } } get_sesslist(ssd->sesslist, FALSE); get_sesslist(ssd->sesslist, TRUE); dlg_refresh(ssd->editbox, dlg); dlg_refresh(ssd->listbox, dlg); } else if (ctrl == ssd->delbutton) { int i = dlg_listbox_index(ssd->listbox, dlg); if (i <= 0) { dlg_beep(dlg); } else { del_settings(ssd->sesslist->sessions[i]); get_sesslist(ssd->sesslist, FALSE); get_sesslist(ssd->sesslist, TRUE); dlg_refresh(ssd->listbox, dlg); } } else if (ctrl == ssd->okbutton) { if (!savedsession) { /* In a mid-session Change Settings, Apply is always OK. */ dlg_end(dlg, 1); return; } /* * Annoying special case. If the `Open' button is * pressed while no host name is currently set, _and_ * the session list previously had the focus, _and_ * there was a session selected in that which had a * valid host name in it, then load it and go. */ if (dlg_last_focused(ctrl, dlg) == ssd->listbox && !*cfg->host) { Config cfg2; if (!load_selected_session(ssd, savedsession, dlg, &cfg2)) { dlg_beep(dlg); return; } /* If at this point we have a valid session, go! */ if (*cfg2.host) { *cfg = cfg2; /* structure copy */ cfg->remote_cmd_ptr = cfg->remote_cmd; /* nasty */ dlg_end(dlg, 1); } else dlg_beep(dlg); } /* * Otherwise, do the normal thing: if we have a valid * session, get going. */ if (*cfg->host) { dlg_end(dlg, 1); } else dlg_beep(dlg); } else if (ctrl == ssd->cancelbutton) { dlg_end(dlg, 0); } }}struct charclass_data { union control *listbox, *editbox, *button;};static void charclass_handler(union control *ctrl, void *dlg, void *data, int event){ Config *cfg = (Config *)data; struct charclass_data *ccd = (struct charclass_data *)ctrl->generic.context.p; if (event == EVENT_REFRESH) { if (ctrl == ccd->listbox) { int i; dlg_update_start(ctrl, dlg); dlg_listbox_clear(ctrl, dlg); for (i = 0; i < 128; i++) { char str[100]; sprintf(str, "%d\t(0x%02X)\t%c\t%d", i, i, (i >= 0x21 && i != 0x7F) ? i : ' ', cfg->wordness[i]); dlg_listbox_add(ctrl, dlg, str); } dlg_update_done(ctrl, dlg); } } else if (event == EVENT_ACTION) { if (ctrl == ccd->button) { char str[100]; int i, n; dlg_editbox_get(ccd->editbox, dlg, str, sizeof(str)); n = atoi(str); for (i = 0; i < 128; i++) { if (dlg_listbox_issel(ccd->listbox, dlg, i)) cfg->wordness[i] = n; } dlg_refresh(ccd->listbox, dlg);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -