?? window.c
字號:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include <assert.h>
#define PUTTY_DO_GLOBALS /* actually _define_ globals */
#include "putty.h"
#include "terminal.h"
#include "storage.h"
#include "win_res.h"
#ifndef NO_MULTIMON
#if WINVER < 0x0500
#define COMPILE_MULTIMON_STUBS
#include <multimon.h>
#endif
#endif
#include <imm.h>
#include <commctrl.h>
#include <richedit.h>
#include <mmsystem.h>
#define IDM_SHOWLOG 0x0010
#define IDM_NEWSESS 0x0020
#define IDM_DUPSESS 0x0030
#define IDM_RECONF 0x0040
#define IDM_CLRSB 0x0050
#define IDM_RESET 0x0060
#define IDM_HELP 0x0140
#define IDM_ABOUT 0x0150
#define IDM_SAVEDSESS 0x0160
#define IDM_COPYALL 0x0170
#define IDM_FULLSCREEN 0x0180
#define IDM_PASTE 0x0190
#define IDM_SESSLGP 0x0250 /* log type printable */
#define IDM_SESSLGA 0x0260 /* log type all chars */
#define IDM_SESSLGE 0x0270 /* log end */
#define IDM_SPECIAL_MIN 0x0400
#define IDM_SPECIAL_MAX 0x0800
#define IDM_SAVED_MIN 0x1000
#define IDM_SAVED_MAX 0x2000
#define WM_IGNORE_CLIP (WM_XUSER + 2)
#define WM_FULLSCR_ON_MAX (WM_XUSER + 3)
#define WM_AGENT_CALLBACK (WM_XUSER + 4)
/* Needed for Chinese support and apparently not always defined. */
#ifndef VK_PROCESSKEY
#define VK_PROCESSKEY 0xE5
#endif
/* Mouse wheel support. */
#ifndef WM_MOUSEWHEEL
#define WM_MOUSEWHEEL 0x020A /* not defined in earlier SDKs */
#endif
#ifndef WHEEL_DELTA
#define WHEEL_DELTA 120
#endif
static Mouse_Button translate_button(Mouse_Button button);
static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
unsigned char *output);
static void cfgtopalette(void);
static void systopalette(void);
static void init_palette(void);
static void init_fonts(int, int);
static void another_font(int);
static void deinit_fonts(void);
static void set_input_locale(HKL);
static int is_full_screen(void);
static void make_full_screen(void);
static void clear_full_screen(void);
static void flip_full_screen(void);
/* Window layout information */
static void reset_window(int);
static int extra_width, extra_height;
static int font_width, font_height, font_dualwidth;
static int offset_width, offset_height;
static int was_zoomed = 0;
static int prev_rows, prev_cols;
static int pending_netevent = 0;
static WPARAM pend_netevent_wParam = 0;
static LPARAM pend_netevent_lParam = 0;
static void enact_pending_netevent(void);
static void flash_window(int mode);
static void sys_cursor_update(void);
static int is_shift_pressed(void);
static int get_fullscreen_rect(RECT * ss);
static time_t last_movement = 0;
static int caret_x = -1, caret_y = -1;
static int kbd_codepage;
static void *ldisc;
static Backend *back;
static void *backhandle;
static struct unicode_data ucsdata;
static int session_closed;
static const struct telnet_special *specials;
static struct {
HMENU menu;
int specials_submenu_pos;
} popup_menus[2];
enum { SYSMENU, CTXMENU };
Config cfg; /* exported to windlg.c */
extern struct sesslist sesslist; /* imported from windlg.c */
struct agent_callback {
void (*callback)(void *, void *, int);
void *callback_ctx;
void *data;
int len;
};
#define FONT_NORMAL 0
#define FONT_BOLD 1
#define FONT_UNDERLINE 2
#define FONT_BOLDUND 3
#define FONT_WIDE 0x04
#define FONT_HIGH 0x08
#define FONT_NARROW 0x10
#define FONT_OEM 0x20
#define FONT_OEMBOLD 0x21
#define FONT_OEMUND 0x22
#define FONT_OEMBOLDUND 0x23
#define FONT_MAXNO 0x2F
#define FONT_SHIFT 5
static HFONT fonts[FONT_MAXNO];
static LOGFONT lfont;
static int fontflag[FONT_MAXNO];
static enum {
BOLD_COLOURS, BOLD_SHADOW, BOLD_FONT
} bold_mode;
static enum {
UND_LINE, UND_FONT
} und_mode;
static int descent;
#define NCOLOURS 24
static COLORREF colours[NCOLOURS];
static HPALETTE pal;
static LPLOGPALETTE logpal;
static RGBTRIPLE defpal[NCOLOURS];
static HWND hwnd;
static HBITMAP caretbm;
static int dbltime, lasttime, lastact;
static Mouse_Button lastbtn;
/* this allows xterm-style mouse handling. */
static int send_raw_mouse = 0;
static int wheel_accumulator = 0;
static char *window_name, *icon_name;
static int compose_state = 0;
static UINT wm_mousewheel = WM_MOUSEWHEEL;
/* Dummy routine, only required in plink. */
void ldisc_update(void *frontend, int echo, int edit)
{
}
int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
{
WNDCLASS wndclass;
MSG msg;
int guess_width, guess_height;
hinst = inst;
flags = FLAG_VERBOSE | FLAG_INTERACTIVE;
sk_init();
InitCommonControls();
/* Ensure a Maximize setting in Explorer doesn't maximise the
* config box. */
defuse_showwindow();
if (!init_winver())
{
char *str = dupprintf("%s Fatal Error", appname);
MessageBox(NULL, "Windows refuses to report a version",
str, MB_OK | MB_ICONEXCLAMATION);
sfree(str);
return 1;
}
/*
* If we're running a version of Windows that doesn't support
* WM_MOUSEWHEEL, find out what message number we should be
* using instead.
*/
if (osVersion.dwMajorVersion < 4 ||
(osVersion.dwMajorVersion == 4 &&
osVersion.dwPlatformId != VER_PLATFORM_WIN32_NT))
wm_mousewheel = RegisterWindowMessage("MSWHEEL_ROLLMSG");
/*
* See if we can find our Help file.
*/
{
char b[2048], *p, *q, *r;
FILE *fp;
GetModuleFileName(NULL, b, sizeof(b) - 1);
r = b;
p = strrchr(b, '\\');
if (p && p >= r) r = p+1;
q = strrchr(b, ':');
if (q && q >= r) r = q+1;
strcpy(r, "putty.hlp");
if ( (fp = fopen(b, "r")) != NULL) {
help_path = dupstr(b);
fclose(fp);
} else
help_path = NULL;
strcpy(r, "putty.cnt");
if ( (fp = fopen(b, "r")) != NULL) {
help_has_contents = TRUE;
fclose(fp);
} else
help_has_contents = FALSE;
}
/*
* Process the command line.
*/
{
char *p;
int got_host = 0;
default_protocol = be_default_protocol;
/* Find the appropriate default port. */
{
int i;
default_port = 0; /* illegal */
for (i = 0; backends[i].backend != NULL; i++)
if (backends[i].protocol == default_protocol) {
default_port = backends[i].backend->default_port;
break;
}
}
cfg.logtype = LGTYP_NONE;
do_defaults(NULL, &cfg);
p = cmdline;
/*
* Process a couple of command-line options which are more
* easily dealt with before the line is broken up into
* words. These are the soon-to-be-defunct @sessionname and
* the internal-use-only &sharedmemoryhandle, neither of
* which are combined with anything else.
*/
while (*p && isspace(*p))
p++;
if (*p == '@') {
int i = strlen(p);
while (i > 1 && isspace(p[i - 1]))
i--;
p[i] = '\0';
do_defaults(p + 1, &cfg);
if (!*cfg.host && !do_config()) {
cleanup_exit(0);
}
} else if (*p == '&') {
/*
* An initial & means we've been given a command line
* containing the hex value of a HANDLE for a file
* mapping object, which we must then extract as a
* config.
*/
HANDLE filemap;
Config *cp;
if (sscanf(p + 1, "%p", &filemap) == 1 &&
(cp = MapViewOfFile(filemap, FILE_MAP_READ,
0, 0, sizeof(Config))) != NULL) {
cfg = *cp;
UnmapViewOfFile(cp);
CloseHandle(filemap);
} else if (!do_config()) {
cleanup_exit(0);
}
} else {
/*
* Otherwise, break up the command line and deal with
* it sensibly.
*/
int argc, i;
char **argv;
split_into_argv(cmdline, &argc, &argv, NULL);
for (i = 0; i < argc; i++) {
char *p = argv[i];
int ret;
ret = cmdline_process_param(p, i+1<argc?argv[i+1]:NULL,
1, &cfg);
if (ret == -2) {
cmdline_error("option \"%s\" requires an argument", p);
} else if (ret == 2) {
i++; /* skip next argument */
} else if (ret == 1) {
continue; /* nothing further needs doing */
} else if (!strcmp(p, "-cleanup")) {
/*
* `putty -cleanup'. Remove all registry
* entries associated with PuTTY, and also find
* and delete the random seed file.
*/
char *s1, *s2;
s1 = dupprintf("This procedure will remove ALL Registry\n"
"entries associated with %s, and will\n"
"also remove the random seed file.\n"
"\n"
"THIS PROCESS WILL DESTROY YOUR SAVED\n"
"SESSIONS. Are you really sure you want\n"
"to continue?", appname);
s2 = dupprintf("%s Warning", appname);
if (MessageBox(NULL, s1, s2,
MB_YESNO | MB_ICONWARNING) == IDYES) {
cleanup_all();
}
sfree(s1);
sfree(s2);
exit(0);
} else if (*p != '-') {
char *q = p;
if (got_host) {
/*
* If we already have a host name, treat
* this argument as a port number. NB we
* have to treat this as a saved -P
* argument, so that it will be deferred
* until it's a good moment to run it.
*/
int ret = cmdline_process_param("-P", p, 1, &cfg);
assert(ret == 2);
} else if (!strncmp(q, "telnet:", 7)) {
/*
* If the hostname starts with "telnet:",
* set the protocol to Telnet and process
* the string as a Telnet URL.
*/
char c;
q += 7;
if (q[0] == '/' && q[1] == '/')
q += 2;
cfg.protocol = PROT_TELNET;
p = q;
while (*p && *p != ':' && *p != '/')
p++;
c = *p;
if (*p)
*p++ = '\0';
if (c == ':')
cfg.port = atoi(p);
else
cfg.port = -1;
strncpy(cfg.host, q, sizeof(cfg.host) - 1);
cfg.host[sizeof(cfg.host) - 1] = '\0';
got_host = 1;
} else {
/*
* Otherwise, treat this argument as a host
* name.
*/
while (*p && !isspace(*p))
p++;
if (*p)
*p++ = '\0';
strncpy(cfg.host, q, sizeof(cfg.host) - 1);
cfg.host[sizeof(cfg.host) - 1] = '\0';
got_host = 1;
}
} else {
cmdline_error("unknown option \"%s\"", p);
}
}
}
cmdline_run_saved(&cfg);
if (!*cfg.host && !do_config()) {
cleanup_exit(0);
}
/*
* Trim leading whitespace off the hostname if it's there.
*/
{
int space = strspn(cfg.host, " \t");
memmove(cfg.host, cfg.host+space, 1+strlen(cfg.host)-space);
}
/* See if host is of the form user@host */
if (cfg.host[0] != '\0') {
char *atsign = strchr(cfg.host, '@');
/* Make sure we're not overflowing the user field */
if (atsign) {
if (atsign - cfg.host < sizeof cfg.username) {
strncpy(cfg.username, cfg.host, atsign - cfg.host);
cfg.username[atsign - cfg.host] = '\0';
}
memmove(cfg.host, atsign + 1, 1 + strlen(atsign + 1));
}
}
/*
* Trim a colon suffix off the hostname if it's there.
*/
cfg.host[strcspn(cfg.host, ":")] = '\0';
/*
* Remove any remaining whitespace from the hostname.
*/
{
int p1 = 0, p2 = 0;
while (cfg.host[p2] != '\0') {
if (cfg.host[p2] != ' ' && cfg.host[p2] != '\t') {
cfg.host[p1] = cfg.host[p2];
p1++;
}
p2++;
}
cfg.host[p1] = '\0';
}
}
/*
* Select protocol. This is farmed out into a table in a
* separate file to enable an ssh-free variant.
*/
{
int i;
back = NULL;
for (i = 0; backends[i].backend != NULL; i++)
if (backends[i].protocol == cfg.protocol) {
back = backends[i].backend;
break;
}
if (back == NULL) {
char *str = dupprintf("%s Internal Error", appname);
MessageBox(NULL, "Unsupported protocol number found",
str, MB_OK | MB_ICONEXCLAMATION);
sfree(str);
cleanup_exit(1);
}
}
/* Check for invalid Port number (i.e. zero) */
if (cfg.port == 0) {
char *str = dupprintf("%s Internal Error", appname);
MessageBox(NULL, "Invalid Port Number",
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -