diff --git a/Recipe b/Recipe index 3e918975..f31d17bb 100644 --- a/Recipe +++ b/Recipe @@ -132,4 +132,5 @@ puttygen : [G] puttygen sshrsag sshdssg sshprime sshdes sshbn sshmd5 version + sshrand noise sshsha winstore misc winctrls sshrsa sshdss + sshpubk sshaes sshsh512 import winutils puttygen.res LIBS -pterm : [X] pterm terminal wcwidth unicode uxmisc +pterm : [X] pterm terminal wcwidth uxucs uxmisc tree234 misc ldisc + + logging uxprint settings pty be_none uxstore diff --git a/be_none.c b/be_none.c index a08a938a..879a20c5 100644 --- a/be_none.c +++ b/be_none.c @@ -4,7 +4,6 @@ * lookups. */ -#include #include #include "putty.h" diff --git a/ldisc.c b/ldisc.c index 131cc428..e6a110b1 100644 --- a/ldisc.c +++ b/ldisc.c @@ -5,7 +5,6 @@ * depending on what's currently configured. */ -#include #include #include diff --git a/logging.c b/logging.c index b311784b..c843118d 100644 --- a/logging.c +++ b/logging.c @@ -1,5 +1,3 @@ -#include - #include #include #include @@ -11,7 +9,6 @@ /* log session to file stuff ... */ static FILE *lgfp = NULL; -static char timdatbuf[20]; static char currlogfilename[FILENAME_MAX]; static void xlatlognam(char *d, char *s, char *hostname, struct tm *tm); @@ -150,7 +147,6 @@ void logfclose(void) static void xlatlognam(char *d, char *s, char *hostname, struct tm *tm) { char buf[10], *bufp; int size; - char *ds = d; /* save start pos. */ int len = FILENAME_MAX-1; while (*s) { @@ -159,6 +155,7 @@ static void xlatlognam(char *d, char *s, char *hostname, struct tm *tm) { if (*s == '&') { char c; s++; + size = 0; if (*s) switch (c = *s++, tolower(c)) { case 'y': size = strftime(buf, sizeof(buf), "%Y", tm); diff --git a/misc.c b/misc.c index f91e8a71..2d0a4634 100644 --- a/misc.c +++ b/misc.c @@ -1,6 +1,6 @@ -#include #include #include +#include #include #include "putty.h" @@ -472,9 +472,7 @@ void *safemalloc(size_t size) #else strcpy(str, "Out of memory!"); #endif - MessageBox(NULL, str, "PuTTY Fatal Error", - MB_SYSTEMMODAL | MB_ICONERROR | MB_OK); - cleanup_exit(1); + modalfatalbox(str); } #ifdef MALLOC_LOG if (fp) @@ -509,9 +507,7 @@ void *saferealloc(void *ptr, size_t size) #else strcpy(str, "Out of memory!"); #endif - MessageBox(NULL, str, "PuTTY Fatal Error", - MB_SYSTEMMODAL | MB_ICONERROR | MB_OK); - cleanup_exit(1); + modalfatalbox(str); } #ifdef MALLOC_LOG if (fp) diff --git a/misc.h b/misc.h index a59317e0..e4e70b1f 100644 --- a/misc.h +++ b/misc.h @@ -54,10 +54,15 @@ void debug_memdump(void *buf, int len, int L); #define dmemdumpl(buf,len) #endif - #ifndef lenof #define lenof(x) ( (sizeof((x))) / (sizeof(*(x)))) #endif +#ifndef min +#define min(x,y) ( (x) < (y) ? (x) : (y) ) +#endif +#ifndef max +#define max(x,y) ( (x) < (y) ? (x) : (y) ) +#endif #endif diff --git a/mkfiles.pl b/mkfiles.pl index d59854d0..68517186 100755 --- a/mkfiles.pl +++ b/mkfiles.pl @@ -481,12 +481,12 @@ print "# TOOLPATH = /opt/gcc/bin\n". "CC = \$(TOOLPATH)cc\n". "\n". -&splitline("CFLAGS = -Wall -O2 -I. -I.. `gtk-config --cflags`")."\n". -"LDFLAGS = -s `gtk-config --libs`\n". +&splitline("CFLAGS = -Wall -g -I. -I.. `gtk-config --cflags`")."\n". +"LDFLAGS = `gtk-config --libs`\n". "\n". ".SUFFIXES:\n". "\n". -"%.o: %.c\n". +"%.o:\n". "\t\$(CC) \$(COMPAT) \$(FWHACK) \$(XFLAGS) \$(CFLAGS) -c \$<\n". "\n"; print &splitline("all:" . join "", map { " $_" } &prognames("X")); diff --git a/pageant.c b/pageant.c index 757091ac..71753c07 100644 --- a/pageant.c +++ b/pageant.c @@ -59,6 +59,22 @@ static char *putty_path; #define PUTTY_DEFAULT "Default%20Settings" static int initial_menuitems_count; +/* + * Print a modal (Really Bad) message box and perform a fatal exit. + */ +void modalfatalbox(char *fmt, ...) +{ + va_list ap; + char stuff[200]; + + va_start(ap, fmt); + vsprintf(stuff, fmt, ap); + va_end(ap); + MessageBox(main_hwnd, stuff, "Pageant Fatal Error", + MB_SYSTEMMODAL | MB_ICONERROR | MB_OK); + exit(1); +} + /* Un-munge session names out of the registry. */ static void unmungestr(char *in, char *out, int outlen) { diff --git a/plink.c b/plink.c index ed4f1345..0d79a984 100644 --- a/plink.c +++ b/plink.c @@ -29,6 +29,17 @@ void fatalbox(char *p, ...) WSACleanup(); cleanup_exit(1); } +void modalfatalbox(char *p, ...) +{ + va_list ap; + fprintf(stderr, "FATAL ERROR: "); + va_start(ap, p); + vfprintf(stderr, p, ap); + va_end(ap); + fputc('\n', stderr); + WSACleanup(); + cleanup_exit(1); +} void connection_fatal(char *p, ...) { va_list ap; diff --git a/psftp.c b/psftp.c index 6f849d4d..4657091f 100644 --- a/psftp.c +++ b/psftp.c @@ -1457,6 +1457,19 @@ void fatalbox(char *fmt, ...) cleanup_exit(1); } +void modalfatalbox(char *fmt, ...) +{ + char str[0x100]; /* Make the size big enough */ + va_list ap; + va_start(ap, fmt); + strcpy(str, "Fatal:"); + vsprintf(str + strlen(str), fmt, ap); + va_end(ap); + strcat(str, "\n"); + fputs(str, stderr); + + cleanup_exit(1); +} void connection_fatal(char *fmt, ...) { char str[0x100]; /* Make the size big enough */ diff --git a/putty.h b/putty.h index e7bb859a..c4230c30 100644 --- a/putty.h +++ b/putty.h @@ -17,6 +17,7 @@ #endif typedef struct config_tag Config; +typedef struct backend_tag Backend; #include "puttyps.h" #include "network.h" @@ -121,6 +122,9 @@ GLOBAL int big_cursor; GLOBAL char *help_path; GLOBAL int help_has_contents; +GLOBAL int nsessions; +GLOBAL char **sessions; + GLOBAL int utf; GLOBAL int dbcs_screenfont; GLOBAL int font_codepage; @@ -199,7 +203,7 @@ enum { COE_ALWAYS /* Always close the window */ }; -typedef struct { +struct backend_tag { char *(*init) (char *host, int port, char **realhost, int nodelay); /* back->send() returns the current amount of buffered data. */ int (*send) (char *buf, int len); @@ -217,7 +221,7 @@ typedef struct { */ void (*unthrottle) (int); int default_port; -} Backend; +}; GLOBAL Backend *back; @@ -427,6 +431,7 @@ void set_raw_mouse_mode(int); Mouse_Button translate_button(Mouse_Button b); void connection_fatal(char *, ...); void fatalbox(char *, ...); +void modalfatalbox(char *, ...); void beep(int); void begin_session(void); void sys_cursor(int x, int y); @@ -460,6 +465,8 @@ void random_destroy_seed(void); void save_settings(char *section, int do_host, Config * cfg); void load_settings(char *section, int do_host, Config * cfg); void get_sesslist(int allocate); +void do_defaults(char *, Config *); +void registry_cleanup(void); /* * Exports from terminal.c. @@ -588,6 +595,15 @@ const char *wc_error(int value); int wc_match(const char *wildcard, const char *target); int wc_unescape(char *output, const char *wildcard); +/* + * Exports from windlg.c + */ +void logevent(char *); +void verify_ssh_host_key(char *host, int port, char *keytype, + char *keystr, char *fingerprint); +void askcipher(char *ciphername, int cs); +int askappend(char *filename); + /* * Exports from console.c (that aren't equivalents to things in * windlg.c). diff --git a/puttygen.c b/puttygen.c index 4e2098e2..4be822ac 100644 --- a/puttygen.c +++ b/puttygen.c @@ -22,6 +22,22 @@ static int requested_help; static char *cmdline_keyfile = NULL; +/* + * Print a modal (Really Bad) message box and perform a fatal exit. + */ +void modalfatalbox(char *fmt, ...) +{ + va_list ap; + char stuff[200]; + + va_start(ap, fmt); + vsprintf(stuff, fmt, ap); + va_end(ap); + MessageBox(NULL, stuff, "PuTTYgen Fatal Error", + MB_SYSTEMMODAL | MB_ICONERROR | MB_OK); + exit(1); +} + /* ---------------------------------------------------------------------- * Progress report code. This is really horrible :-) */ diff --git a/scp.c b/scp.c index 5ebcfd2c..a24d62fb 100644 --- a/scp.c +++ b/scp.c @@ -234,6 +234,29 @@ void fatalbox(char *fmt, ...) cleanup_exit(1); } +void modalfatalbox(char *fmt, ...) +{ + char str[0x100]; /* Make the size big enough */ + va_list ap; + va_start(ap, fmt); + strcpy(str, "Fatal: "); + vsprintf(str + strlen(str), fmt, ap); + va_end(ap); + strcat(str, "\n"); + tell_str(stderr, str); + errs++; + + if (gui_mode) { + unsigned int msg_id = WM_RET_ERR_CNT; + if (list) + msg_id = WM_LS_RET_ERR_CNT; + while (!PostMessage + ((HWND) atoi(gui_hwnd), msg_id, (WPARAM) errs, + 0 /*lParam */ ))SleepEx(1000, TRUE); + } + + cleanup_exit(1); +} void connection_fatal(char *fmt, ...) { char str[0x100]; /* Make the size big enough */ diff --git a/settings.c b/settings.c index ef0446f3..4bc11ec5 100644 --- a/settings.c +++ b/settings.c @@ -2,7 +2,6 @@ * settings.c: read and write saved sessions. */ -#include #include #include #include "putty.h" @@ -464,8 +463,11 @@ void load_settings(char *section, int do_host, Config * cfg) gppi(sesskey, "TermHeight", 24, &cfg->height); gpps(sesskey, "Font", "Courier New", cfg->font, sizeof(cfg->font)); gppi(sesskey, "FontIsBold", 0, &cfg->fontisbold); +#ifdef _WINDOWS gppi(sesskey, "FontCharSet", ANSI_CHARSET, &cfg->fontcharset); +#endif gppi(sesskey, "FontHeight", 10, &cfg->fontheight); +#ifdef _WINDOWS if (cfg->fontheight < 0) { int oldh, newh; HDC hdc = GetDC(NULL); @@ -478,6 +480,7 @@ void load_settings(char *section, int do_host, Config * cfg) newh--; cfg->fontheight = newh; } +#endif gppi(sesskey, "FontVTMode", VT_UNICODE, (int *) &cfg->vtmode); gppi(sesskey, "TryPalette", 0, &cfg->try_palette); gppi(sesskey, "BoldAsColour", 1, &cfg->bold_colour); diff --git a/terminal.c b/terminal.c index b286efe1..7a6c5bce 100644 --- a/terminal.c +++ b/terminal.c @@ -1042,6 +1042,9 @@ static void term_print_finish(void) int len, size; char c; + if (!printing && !only_printing) + return; /* we need do nothing */ + term_print_flush(); while ((size = bufchain_size(&printer_buf)) > 0) { bufchain_prefix(&printer_buf, &data, &len); @@ -1072,6 +1075,7 @@ void term_out(void) unget = -1; + chars = NULL; /* placate compiler warnings */ while (nchars > 0 || bufchain_size(&inbuf) > 0) { if (unget == -1) { if (nchars == 0) { @@ -3176,16 +3180,14 @@ static void clipme(pos top, pos bottom, int rect) unsigned char buf[4]; WCHAR wbuf[4]; int rv; - if (IsDBCSLeadByteEx(font_codepage, (BYTE) c)) { + if (is_dbcs_leadbyte(font_codepage, (BYTE) c)) { buf[0] = c; buf[1] = (unsigned char) ldata[top.x + 1]; - rv = MultiByteToWideChar(font_codepage, - 0, buf, 2, wbuf, 4); + rv = mb_to_wc(font_codepage, 0, buf, 2, wbuf, 4); top.x++; } else { buf[0] = c; - rv = MultiByteToWideChar(font_codepage, - 0, buf, 1, wbuf, 4); + rv = mb_to_wc(font_codepage, 0, buf, 1, wbuf, 4); } if (rv > 0) { diff --git a/unicode.c b/unicode.c index e8542211..f8cd3b51 100644 --- a/unicode.c +++ b/unicode.c @@ -614,8 +614,7 @@ void lpage_send(int codepage, char *buf, int len, int interactive) widesize = len * 2; } - wclen = - MultiByteToWideChar(codepage, 0, buf, len, widebuffer, widesize); + wclen = mb_to_wc(codepage, 0, buf, len, widebuffer, widesize); luni_send(widebuffer, wclen, interactive); } @@ -653,8 +652,8 @@ void luni_send(wchar_t * widebuf, int len, int interactive) } } else if (!uni_tbl) { int rv; - rv = WideCharToMultiByte(line_codepage, 0, widebuf, len, - linebuffer, linesize, NULL, NULL); + rv = wc_to_mb(line_codepage, 0, widebuf, len, + linebuffer, linesize, NULL, NULL); if (rv >= 0) p = linebuffer + rv; else @@ -1243,7 +1242,7 @@ void get_unitab(int codepage, wchar_t * unitab, int ftype) for (i = 0; i < max; i++) { tbuf[0] = i; - if (MultiByteToWideChar(codepage, flg, tbuf, 1, unitab + i, 1) + if (mb_to_wc(codepage, flg, tbuf, 1, unitab + i, 1) != 1) unitab[i] = 0xFFFD; } diff --git a/unix/pterm.c b/unix/pterm.c index d29762a3..082a2711 100644 --- a/unix/pterm.c +++ b/unix/pterm.c @@ -5,14 +5,137 @@ #include #include +#include #include #include +#define PUTTY_DO_GLOBALS /* actually _define_ globals */ +#include "putty.h" + #define CAT2(x,y) x ## y #define CAT(x,y) CAT2(x,y) #define ASSERT(x) enum {CAT(assertion_,__LINE__) = 1 / (x)} -#define lenof(x) (sizeof((x))/sizeof(*(x))) +void ldisc_update(int echo, int edit) +{ + /* + * This is a stub in pterm. If I ever produce a Unix + * command-line ssh/telnet/rlogin client (i.e. a port of plink) + * then it will require some termios manoeuvring analogous to + * that in the Windows plink.c, but here it's meaningless. + */ +} + +int askappend(char *filename) +{ + /* + * FIXME: for the moment we just wipe the log file. Since I + * haven't yet enabled logging, this shouldn't matter yet! + */ + return 2; +} + +void logevent(char *string) +{ + /* + * FIXME: event log entries are currently ignored. + */ +} + +/* + * Translate a raw mouse button designation (LEFT, MIDDLE, RIGHT) + * into a cooked one (SELECT, EXTEND, PASTE). + * + * In Unix, this is not configurable; the X button arrangement is + * rock-solid across all applications, everyone has a three-button + * mouse or a means of faking it, and there is no need to switch + * buttons around at all. + */ +Mouse_Button translate_button(Mouse_Button button) +{ + if (button == MBT_LEFT) + return MBT_SELECT; + if (button == MBT_MIDDLE) + return MBT_PASTE; + if (button == MBT_RIGHT) + return MBT_EXTEND; + return 0; /* shouldn't happen */ +} + +/* + * Minimise or restore the window in response to a server-side + * request. + */ +void set_iconic(int iconic) +{ + /* FIXME: currently ignored */ +} + +/* + * Move the window in response to a server-side request. + */ +void move_window(int x, int y) +{ + /* FIXME: currently ignored */ +} + +/* + * Move the window to the top or bottom of the z-order in response + * to a server-side request. + */ +void set_zorder(int top) +{ + /* FIXME: currently ignored */ +} + +/* + * Refresh the window in response to a server-side request. + */ +void refresh_window(void) +{ + /* FIXME: currently ignored */ +} + +/* + * Maximise or restore the window in response to a server-side + * request. + */ +void set_zoomed(int zoomed) +{ + /* FIXME: currently ignored */ +} + +/* + * Report whether the window is iconic, for terminal reports. + */ +int is_iconic(void) +{ + return 0; /* FIXME */ +} + +/* + * Report the window's position, for terminal reports. + */ +void get_window_pos(int *x, int *y) +{ + *x = 3; *y = 4; /* FIXME */ +} + +/* + * Report the window's pixel size, for terminal reports. + */ +void get_window_pixels(int *x, int *y) +{ + *x = 1; *y = 2; /* FIXME */ +} + +/* + * Return the window or icon title. + */ +char *get_window_title(int icon) +{ + return "FIXME: window title retrieval not yet implemented"; +} struct gui_data { GtkWidget *area; @@ -20,6 +143,9 @@ struct gui_data { GdkGC *black_gc, *white_gc; }; +static struct gui_data the_inst; +static struct gui_data *inst = &the_inst; /* so we always write `inst->' */ + gint delete_window(GtkWidget *widget, GdkEvent *event, gpointer data) { /* @@ -86,13 +212,17 @@ gint configure_area(GtkWidget *widget, GdkEventConfigure *event, gpointer data) gint expose_area(GtkWidget *widget, GdkEventExpose *event, gpointer data) { - struct gui_data *inst = (struct gui_data *)data; + /* struct gui_data *inst = (struct gui_data *)data; */ /* - * FIXME: pass the exposed rect to terminal.c which will call - * us back to do the actual painting. + * Pass the exposed rectangle to terminal.c, which will call us + * back to do the actual painting. */ - return FALSE; + term_paint(NULL, + event->area.x / 9, event->area.y / 15, + (event->area.x + event->area.width - 1) / 9, + (event->area.y + event->area.height - 1) / 15); + return TRUE; } #define KEY_PRESSED(k) \ @@ -100,20 +230,23 @@ gint expose_area(GtkWidget *widget, GdkEventExpose *event, gpointer data) gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) { - struct gui_data *inst = (struct gui_data *)data; + /* struct gui_data *inst = (struct gui_data *)data; */ - /* - * FIXME: all sorts of fun keyboard handling required here. - */ + if (event->type == GDK_KEY_PRESS) { + char c[1]; + c[0] = event->keyval; + ldisc_send(c, 1, 1); + term_out(); + } + + return TRUE; } gint timer_func(gpointer data) { - struct gui_data *inst = (struct gui_data *)data; + /* struct gui_data *inst = (struct gui_data *)data; */ - /* - * FIXME: we're bound to need this sooner or later! - */ + term_update(); return TRUE; } @@ -127,16 +260,150 @@ gint focus_event(GtkWidget *widget, GdkEventFocus *event, gpointer data) /* * FIXME: need to faff with the cursor shape. */ + return FALSE; +} + +/* + * set or clear the "raw mouse message" mode + */ +void set_raw_mouse_mode(int activate) +{ + /* FIXME: currently ignored */ +} + +void request_resize(int w, int h) +{ + /* FIXME: currently ignored */ +} + +void palette_set(int n, int r, int g, int b) +{ + /* FIXME: currently ignored */ +} +void palette_reset(void) +{ + /* FIXME: currently ignored */ +} + +void write_clip(wchar_t * data, int len, int must_deselect) +{ + /* FIXME: currently ignored */ +} + +void get_clip(wchar_t ** p, int *len) +{ + if (p) { + /* FIXME: currently nonfunctional */ + *p = NULL; + *len = 0; + } +} + +void set_title(char *title) +{ + /* FIXME: currently ignored */ +} + +void set_icon(char *title) +{ + /* FIXME: currently ignored */ +} + +void set_sbar(int total, int start, int page) +{ + /* FIXME: currently ignored */ +} + +void sys_cursor(int x, int y) +{ + /* + * This is meaningless under X. + */ +} + +void beep(int mode) +{ + gdk_beep(); +} + +int CharWidth(Context ctx, int uc) +{ + /* + * Under X, any fixed-width font really _is_ fixed-width. + * Double-width characters will be dealt with using a separate + * font. For the moment we can simply return 1. + */ + return 1; +} + +Context get_ctx(void) +{ + GdkGC *gc = gdk_gc_new(inst->area->window); + return gc; +} + +void free_ctx(Context ctx) +{ + GdkGC *gc = (GdkGC *)ctx; + gdk_gc_unref(gc); +} + +/* + * Draw a line of text in the window, at given character + * coordinates, in given attributes. + * + * We are allowed to fiddle with the contents of `text'. + */ +void do_text(Context ctx, int x, int y, char *text, int len, + unsigned long attr, int lattr) +{ + GdkColor fg, bg; + + GdkGC *gc = (GdkGC *)ctx; + fg.red = fg.green = fg.blue = 65535; + bg.red = bg.green = bg.blue = 65535; + gdk_gc_set_foreground(gc, &fg); + gdk_gc_set_background(gc, &bg); + + gdk_draw_text(inst->area->window, inst->fonts[0], inst->white_gc, + x*9, y*15 + inst->fonts[0]->ascent, text, len); +} + +void do_cursor(Context ctx, int x, int y, char *text, int len, + unsigned long attr, int lattr) +{ + /* FIXME: passive cursor NYI */ + if (attr & TATTR_PASCURS) { + attr &= ~TATTR_PASCURS; + attr |= TATTR_ACTCURS; + } + do_text(ctx, x, y, text, len, attr, lattr); +} + +void modalfatalbox(char *p, ...) +{ + va_list ap; + fprintf(stderr, "FATAL ERROR: "); + va_start(ap, p); + vfprintf(stderr, p, ap); + va_end(ap); + fputc('\n', stderr); + exit(1); } int main(int argc, char **argv) { GtkWidget *window; - struct gui_data the_inst; - struct gui_data *inst = &the_inst; /* so we always write `inst->' */ gtk_init(&argc, &argv); + do_defaults(NULL, &cfg); + + init_ucs(); + + back = &pty_backend; + back->init(NULL, 0, NULL, 0); + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); inst->area = gtk_drawing_area_new(); gtk_drawing_area_size(GTK_DRAWING_AREA(inst->area), @@ -167,6 +434,9 @@ int main(int argc, char **argv) gtk_widget_show(inst->area); gtk_widget_show(window); + term_init(); + term_size(24, 80, 2000); + gtk_main(); return 0; diff --git a/unix/pty.c b/unix/pty.c new file mode 100644 index 00000000..291247ee --- /dev/null +++ b/unix/pty.c @@ -0,0 +1,107 @@ +#include +#include + +#include "putty.h" + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +static void pty_size(void); + +static void c_write(char *buf, int len) +{ + from_backend(0, buf, len); +} + +/* + * Called to set up the pty. + * + * Returns an error message, or NULL on success. + * + * Also places the canonical host name into `realhost'. It must be + * freed by the caller. + */ +static char *pty_init(char *host, int port, char **realhost, int nodelay) +{ + /* FIXME: do nothing for now */ + return NULL; +} + +/* + * Called to send data down the pty. + */ +static int pty_send(char *buf, int len) +{ + c_write(buf, len); /* FIXME: diagnostic thingy */ + return 0; +} + +/* + * Called to query the current socket sendability status. + */ +static int pty_sendbuffer(void) +{ + return 0; +} + +/* + * Called to set the size of the window + */ +static void pty_size(void) +{ + /* FIXME: will need to do TIOCSWINSZ or whatever. */ + return; +} + +/* + * Send special codes. + */ +static void pty_special(Telnet_Special code) +{ + /* Do nothing! */ + return; +} + +static Socket pty_socket(void) +{ + return NULL; /* shouldn't ever be needed */ +} + +static int pty_sendok(void) +{ + return 1; +} + +static void pty_unthrottle(int backlog) +{ + /* do nothing */ +} + +static int pty_ldisc(int option) +{ + return 0; /* neither editing nor echoing */ +} + +static int pty_exitcode(void) +{ + /* Shouldn't ever be required */ + return 0; +} + +Backend pty_backend = { + pty_init, + pty_send, + pty_sendbuffer, + pty_size, + pty_special, + pty_socket, + pty_exitcode, + pty_sendok, + pty_ldisc, + pty_unthrottle, + 1 +}; diff --git a/unix/unix.h b/unix/unix.h index 6a40e4ab..a7f3fa59 100644 --- a/unix/unix.h +++ b/unix/unix.h @@ -3,6 +3,8 @@ typedef void *Context; /* FIXME: probably needs changing */ +extern Backend pty_backend; + /* Simple wraparound timer function */ unsigned long getticks(void); /* based on gettimeofday(2) */ #define GETTICKCOUNT getticks @@ -12,6 +14,10 @@ unsigned long getticks(void); /* based on gettimeofday(2) */ #define WCHAR wchar_t #define BYTE unsigned char +int is_dbcs_leadbyte(int codepage, char byte); +int mb_to_wc(int codepage, int flags, char *mbstr, int mblen, + wchar_t *wcstr, int wclen); +void init_ucs(void); #define DEFAULT_CODEPAGE 0 /* FIXME: no idea how to do this */ diff --git a/unix/uxprint.c b/unix/uxprint.c new file mode 100644 index 00000000..6558317b --- /dev/null +++ b/unix/uxprint.c @@ -0,0 +1,24 @@ +/* + * Printing interface for PuTTY. + */ + +#include +#include "putty.h" + +printer_job *printer_start_job(char *printer) +{ + /* FIXME: open pipe to lpr */ + return NULL; +} + +void printer_job_data(printer_job *pj, void *data, int len) +{ + /* FIXME: receive a pipe to lpr, write things to it */ + assert(!"We shouldn't get here"); +} + +void printer_finish_job(printer_job *pj) +{ + /* FIXME: receive a pipe to lpr, close it */ + assert(!"We shouldn't get here either"); +} diff --git a/unix/uxstore.c b/unix/uxstore.c new file mode 100644 index 00000000..76e19c10 --- /dev/null +++ b/unix/uxstore.c @@ -0,0 +1,86 @@ +/* + * uxstore.c: Unix-specific implementation of the interface defined + * in storage.h. + */ + +#include +#include +#include "putty.h" +#include "storage.h" + +/* FIXME. For the moment, we do nothing at all here. */ + +void *open_settings_w(char *sessionname) +{ + return NULL; +} + +void write_setting_s(void *handle, char *key, char *value) +{ +} + +void write_setting_i(void *handle, char *key, int value) +{ +} + +void close_settings_w(void *handle) +{ +} + +void *open_settings_r(char *sessionname) +{ + return NULL; +} + +char *read_setting_s(void *handle, char *key, char *buffer, int buflen) +{ + return NULL; +} + +int read_setting_i(void *handle, char *key, int defvalue) +{ + return defvalue; +} + +void close_settings_r(void *handle) +{ +} + +void del_settings(char *sessionname) +{ +} + +void *enum_settings_start(void) +{ + return NULL; +} + +char *enum_settings_next(void *handle, char *buffer, int buflen) +{ + return NULL; +} + +void enum_settings_finish(void *handle) +{ +} + +int verify_host_key(char *hostname, int port, char *keytype, char *key) +{ + return 1; /* key does not exist in registry */ +} + +void store_host_key(char *hostname, int port, char *keytype, char *key) +{ +} + +void read_random_seed(noise_consumer_t consumer) +{ +} + +void write_random_seed(void *data, int len) +{ +} + +void cleanup_all(void) +{ +} diff --git a/unix/uxucs.c b/unix/uxucs.c new file mode 100644 index 00000000..fbd4e967 --- /dev/null +++ b/unix/uxucs.c @@ -0,0 +1,114 @@ +#include +#include +#include + +#include +#include "putty.h" +#include "misc.h" + +/* + * Unix Unicode-handling routines. + * + * FIXME: currently trivial stub versions assuming all codepages + * are ISO8859-1. + */ + +void lpage_send(int codepage, char *buf, int len, int interactive) +{ + ldisc_send(buf, len, interactive); +} + +void luni_send(wchar_t * widebuf, int len, int interactive) +{ + static char *linebuffer = 0; + static int linesize = 0; + int ratio = (in_utf)?6:1; + int i; + char *p; + + if (len * ratio > linesize) { + sfree(linebuffer); + linebuffer = smalloc(len * ratio * 2 * sizeof(wchar_t)); + linesize = len * ratio * 2; + } + + if (in_utf) { + /* UTF is a simple algorithm */ + for (p = linebuffer, i = 0; i < len; i++) { + wchar_t ch = widebuf[i]; + + if ((ch&0xF800) == 0xD800) ch = '.'; + + if (ch < 0x80) { + *p++ = (char) (ch); + } else if (ch < 0x800) { + *p++ = (0xC0 | (ch >> 6)); + *p++ = (0x80 | (ch & 0x3F)); + } else if (ch < 0x10000) { + *p++ = (0xE0 | (ch >> 12)); + *p++ = (0x80 | ((ch >> 6) & 0x3F)); + *p++ = (0x80 | (ch & 0x3F)); + } else if (ch < 0x200000) { + *p++ = (0xF0 | (ch >> 18)); + *p++ = (0x80 | ((ch >> 12) & 0x3F)); + *p++ = (0x80 | ((ch >> 6) & 0x3F)); + *p++ = (0x80 | (ch & 0x3F)); + } else if (ch < 0x4000000) { + *p++ = (0xF8 | (ch >> 24)); + *p++ = (0x80 | ((ch >> 18) & 0x3F)); + *p++ = (0x80 | ((ch >> 12) & 0x3F)); + *p++ = (0x80 | ((ch >> 6) & 0x3F)); + *p++ = (0x80 | (ch & 0x3F)); + } else { + *p++ = (0xFC | (ch >> 30)); + *p++ = (0x80 | ((ch >> 24) & 0x3F)); + *p++ = (0x80 | ((ch >> 18) & 0x3F)); + *p++ = (0x80 | ((ch >> 12) & 0x3F)); + *p++ = (0x80 | ((ch >> 6) & 0x3F)); + *p++ = (0x80 | (ch & 0x3F)); + } + } + } else { + for (p = linebuffer, i = 0; i < len; i++) { + wchar_t ch = widebuf[i]; + if (ch < 0x100) + *p++ = (char) ch; + else + *p++ = '.'; + } + } + if (p > linebuffer) + ldisc_send(linebuffer, p - linebuffer, interactive); +} + +int is_dbcs_leadbyte(int codepage, char byte) +{ + return 0; /* we don't do DBCS */ +} + +int mb_to_wc(int codepage, int flags, char *mbstr, int mblen, + wchar_t *wcstr, int wclen) +{ + int ret = 0; + while (mblen > 0 && wclen > 0) { + *wcstr++ = (unsigned char) *mbstr++; + ret++; + } + return ret; /* FIXME: check error codes! */ +} + +void init_ucs(void) +{ + int i; + /* Find the line control characters. FIXME: this is not right. */ + for (i = 0; i < 256; i++) + if (i < ' ' || (i >= 0x7F && i < 0xA0)) + unitab_ctrl[i] = i; + else + unitab_ctrl[i] = 0xFF; + + for (i = 0; i < 256; i++) { + unitab_line[i] = unitab_scoacs[i] = i; + unitab_xterm[i] = i & 0x1F; + } +} \ No newline at end of file diff --git a/window.c b/window.c index 9ea6c018..59757d91 100644 --- a/window.c +++ b/window.c @@ -4201,6 +4201,22 @@ void fatalbox(char *fmt, ...) cleanup_exit(1); } +/* + * Print a modal (Really Bad) message box and perform a fatal exit. + */ +void modalfatalbox(char *fmt, ...) +{ + va_list ap; + char stuff[200]; + + va_start(ap, fmt); + vsprintf(stuff, fmt, ap); + va_end(ap); + MessageBox(hwnd, stuff, "PuTTY Fatal Error", + MB_SYSTEMMODAL | MB_ICONERROR | MB_OK); + cleanup_exit(1); +} + /* * Manage window caption / taskbar flashing, if enabled. * 0 = stop, 1 = maintain, 2 = start diff --git a/winstuff.h b/winstuff.h index f21053f7..3bf43bcb 100644 --- a/winstuff.h +++ b/winstuff.h @@ -143,24 +143,23 @@ void fwdsetter(struct ctlpos *cp, int listid, char *stext, int sid, void defuse_showwindow(void); int do_config(void); int do_reconfig(HWND); -void do_defaults(char *, Config *); -void logevent(char *); void showeventlog(HWND); void showabout(HWND); -void verify_ssh_host_key(char *host, int port, char *keytype, - char *keystr, char *fingerprint); -void askcipher(char *ciphername, int cs); -int askappend(char *filename); -void registry_cleanup(void); void force_normal(HWND hwnd); -GLOBAL int nsessions; -GLOBAL char **sessions; - /* * Exports from sizetip.c. */ void UpdateSizeTip(HWND src, int cx, int cy); void EnableSizeTip(int bEnable); +/* + * Unicode and multi-byte character handling stuff. + */ +#define is_dbcs_leadbyte(cp, c) IsDBCSLeadByteEx(cp, c) +#define mb_to_wc(cp, flags, mbstr, mblen, wcstr, wclen) \ + MultiByteToWideChar(cp, flags, mbstr, mblen, wcstr, wclen) +#define wc_to_mb(cp, flags, wcstr, wclen, mbstr, mblen, def, defused) \ + WideCharToMultiByte(cp, flags, mbstr, mblen, wcstr, wclen, def,defused) + #endif