OSDN Git Service

Modify features and documents for 1.98b the urgent security release.
[ffftp/ffftp.git] / contrib / putty / MACOSX / OSXWIN.M
diff --git a/contrib/putty/MACOSX/OSXWIN.M b/contrib/putty/MACOSX/OSXWIN.M
deleted file mode 100644 (file)
index 9de1e08..0000000
+++ /dev/null
@@ -1,1227 +0,0 @@
-/*\r
- * osxwin.m: code to manage a session window in Mac OS X PuTTY.\r
- */\r
-\r
-#import <Cocoa/Cocoa.h>\r
-#include "putty.h"\r
-#include "terminal.h"\r
-#include "osxclass.h"\r
-\r
-/* Colours come in two flavours: configurable, and xterm-extended. */\r
-#define NCFGCOLOURS (lenof(((Config *)0)->colours))\r
-#define NEXTCOLOURS 240 /* 216 colour-cube plus 24 shades of grey */\r
-#define NALLCOLOURS (NCFGCOLOURS + NEXTCOLOURS)\r
-\r
-/*\r
- * The key component of the per-session data is the SessionWindow\r
- * class. A pointer to this is used as the frontend handle, to be\r
- * passed to all the platform-independent subsystems that require\r
- * one.\r
- */\r
-\r
-@interface TerminalView : NSImageView\r
-{\r
-    NSFont *font;\r
-    NSImage *image;\r
-    Terminal *term;\r
-    Config cfg;\r
-    NSColor *colours[NALLCOLOURS];\r
-    float fw, fasc, fdesc, fh;\r
-}\r
-- (void)drawStartFinish:(BOOL)start;\r
-- (void)setColour:(int)n r:(float)r g:(float)g b:(float)b;\r
-- (void)doText:(wchar_t *)text len:(int)len x:(int)x y:(int)y\r
-    attr:(unsigned long)attr lattr:(int)lattr;\r
-@end\r
-\r
-@implementation TerminalView\r
-- (BOOL)isFlipped\r
-{\r
-    return YES;\r
-}\r
-- (id)initWithTerminal:(Terminal *)aTerm config:(Config)aCfg\r
-{\r
-    float w, h;\r
-\r
-    self = [self initWithFrame:NSMakeRect(0,0,100,100)];\r
-\r
-    term = aTerm;\r
-    cfg = aCfg;\r
-\r
-    /*\r
-     * Initialise the fonts we're going to use.\r
-     * \r
-     * FIXME: for the moment I'm sticking with exactly one default font.\r
-     */\r
-    font = [NSFont userFixedPitchFontOfSize:0];\r
-\r
-    /*\r
-     * Now determine the size of the primary font.\r
-     * \r
-     * FIXME: If we have multiple fonts, we may need to set fasc\r
-     * and fdesc to the _maximum_ asc and desc out of all the\r
-     * fonts, _before_ adding them together to get fh.\r
-     */\r
-    fw = [font widthOfString:@"A"];\r
-    fasc = [font ascender];\r
-    fdesc = -[font descender];\r
-    fh = fasc + fdesc;\r
-    fh = (int)fh + (fh > (int)fh);     /* round up, ickily */\r
-\r
-    /*\r
-     * Use this to figure out the size of the terminal view.\r
-     */\r
-    w = fw * term->cols;\r
-    h = fh * term->rows;\r
-\r
-    /*\r
-     * And set our size and subimage.\r
-     */\r
-    image = [[NSImage alloc] initWithSize:NSMakeSize(w,h)];\r
-    [image setFlipped:YES];\r
-    [self setImage:image];\r
-    [self setFrame:NSMakeRect(0,0,w,h)];\r
-\r
-    term_invalidate(term);\r
-\r
-    return self;\r
-}\r
-- (void)drawStartFinish:(BOOL)start\r
-{\r
-    if (start)\r
-       [image lockFocus];\r
-    else\r
-       [image unlockFocus];\r
-}\r
-- (void)doText:(wchar_t *)text len:(int)len x:(int)x y:(int)y\r
-    attr:(unsigned long)attr lattr:(int)lattr\r
-{\r
-    int nfg, nbg, rlen, widefactor;\r
-    float ox, oy, tw, th;\r
-    NSDictionary *attrdict;\r
-\r
-    /* FIXME: TATTR_COMBINING */\r
-\r
-    nfg = ((attr & ATTR_FGMASK) >> ATTR_FGSHIFT);\r
-    nbg = ((attr & ATTR_BGMASK) >> ATTR_BGSHIFT);\r
-    if (attr & ATTR_REVERSE) {\r
-       int t = nfg;\r
-       nfg = nbg;\r
-       nbg = t;\r
-    }\r
-    if (cfg.bold_colour && (attr & ATTR_BOLD)) {\r
-       if (nfg < 16) nfg |= 8;\r
-       else if (nfg >= 256) nfg |= 1;\r
-    }\r
-    if (cfg.bold_colour && (attr & ATTR_BLINK)) {\r
-       if (nbg < 16) nbg |= 8;\r
-       else if (nbg >= 256) nbg |= 1;\r
-    }\r
-    if (attr & TATTR_ACTCURS) {\r
-       nfg = 260;\r
-       nbg = 261;\r
-    }\r
-\r
-    if (attr & ATTR_WIDE) {\r
-       widefactor = 2;\r
-       /* FIXME: what do we actually have to do about wide characters? */\r
-    } else {\r
-       widefactor = 1;\r
-    }\r
-\r
-    /* FIXME: ATTR_BOLD without cfg.bold_colour */\r
-\r
-    if ((lattr & LATTR_MODE) != LATTR_NORM) {\r
-       x *= 2;\r
-       if (x >= term->cols)\r
-           return;\r
-       if (x + len*2*widefactor > term->cols)\r
-           len = (term->cols-x)/2/widefactor;/* trim to LH half */\r
-       rlen = len * 2;\r
-    } else\r
-       rlen = len;\r
-\r
-    /* FIXME: how do we actually implement double-{width,height} lattrs? */\r
-\r
-    ox = x * fw;\r
-    oy = y * fh;\r
-    tw = rlen * widefactor * fw;\r
-    th = fh;\r
-\r
-    /*\r
-     * Set the clipping rectangle.\r
-     */\r
-    [[NSGraphicsContext currentContext] saveGraphicsState];\r
-    [NSBezierPath clipRect:NSMakeRect(ox, oy, tw, th)];\r
-\r
-    attrdict = [NSDictionary dictionaryWithObjectsAndKeys:\r
-               colours[nfg], NSForegroundColorAttributeName,\r
-               colours[nbg], NSBackgroundColorAttributeName,\r
-               font, NSFontAttributeName, nil];\r
-\r
-    /*\r
-     * Create an NSString and draw it.\r
-     * \r
-     * Annoyingly, although our input is wchar_t which is four\r
-     * bytes wide on OS X and terminal.c supports 32-bit Unicode,\r
-     * we must convert into the two-byte type `unichar' to store in\r
-     * NSString, so we lose display capability for extra-BMP stuff\r
-     * at this point.\r
-     */\r
-    {\r
-       NSString *string;\r
-       unichar *utext;\r
-       int i;\r
-\r
-       utext = snewn(len, unichar);\r
-       for (i = 0; i < len; i++)\r
-           utext[i] = (text[i] >= 0x10000 ? 0xFFFD : text[i]);\r
-\r
-       string = [NSString stringWithCharacters:utext length:len];\r
-       [string drawAtPoint:NSMakePoint(ox, oy) withAttributes:attrdict];\r
-\r
-       sfree(utext);\r
-    }\r
-\r
-    /*\r
-     * Restore the graphics state from before the clipRect: call.\r
-     */\r
-    [[NSGraphicsContext currentContext] restoreGraphicsState];\r
-\r
-    /*\r
-     * And flag this area as needing display.\r
-     */\r
-    [self setNeedsDisplayInRect:NSMakeRect(ox, oy, tw, th)];\r
-}\r
-\r
-- (void)setColour:(int)n r:(float)r g:(float)g b:(float)b\r
-{\r
-    assert(n >= 0 && n < lenof(colours));\r
-    colours[n] = [[NSColor colorWithDeviceRed:r green:g blue:b alpha:1.0]\r
-                 retain];\r
-}\r
-@end\r
-\r
-@implementation SessionWindow\r
-- (id)initWithConfig:(Config)aCfg\r
-{\r
-    NSRect rect = { {0,0}, {0,0} };\r
-\r
-    alert_ctx = NULL;\r
-\r
-    cfg = aCfg;                               /* structure copy */\r
-\r
-    init_ucs(&ucsdata, cfg.line_codepage, cfg.utf8_override,\r
-            CS_UTF8, cfg.vtmode);\r
-    term = term_init(&cfg, &ucsdata, self);\r
-    logctx = log_init(self, &cfg);\r
-    term_provide_logctx(term, logctx);\r
-    term_size(term, cfg.height, cfg.width, cfg.savelines);\r
-\r
-    termview = [[[TerminalView alloc] initWithTerminal:term config:cfg]\r
-               autorelease];\r
-\r
-    /*\r
-     * Now work out the size of the window.\r
-     */\r
-    rect = [termview frame];\r
-    rect.origin = NSMakePoint(0,0);\r
-    rect.size.width += 2 * cfg.window_border;\r
-    rect.size.height += 2 * cfg.window_border;\r
-\r
-    /*\r
-     * Set up a backend.\r
-     */\r
-    back = backend_from_proto(cfg.protocol);\r
-    if (!back)\r
-       back = &pty_backend;\r
-\r
-    {\r
-       const char *error;\r
-       char *realhost = NULL;\r
-       error = back->init(self, &backhandle, &cfg, cfg.host, cfg.port,\r
-                          &realhost, cfg.tcp_nodelay, cfg.tcp_keepalives);\r
-       if (error) {\r
-           fatalbox("%s\n", error);   /* FIXME: connection_fatal at worst */\r
-       }\r
-\r
-       if (realhost)\r
-           sfree(realhost);           /* FIXME: do something with this */\r
-    }\r
-    back->provide_logctx(backhandle, logctx);\r
-\r
-    /*\r
-     * Create a line discipline. (This must be done after creating\r
-     * the terminal _and_ the backend, since it needs to be passed\r
-     * pointers to both.)\r
-     */\r
-    ldisc = ldisc_create(&cfg, term, back, backhandle, self);\r
-\r
-    /*\r
-     * FIXME: Set up a scrollbar.\r
-     */\r
-\r
-    self = [super initWithContentRect:rect\r
-           styleMask:(NSTitledWindowMask | NSMiniaturizableWindowMask |\r
-                      NSClosableWindowMask)\r
-           backing:NSBackingStoreBuffered\r
-           defer:YES];\r
-    [self setTitle:@"PuTTY"];\r
-\r
-    [self setIgnoresMouseEvents:NO];\r
-\r
-    /*\r
-     * Put the terminal view in the window.\r
-     */\r
-    rect = [termview frame];\r
-    rect.origin = NSMakePoint(cfg.window_border, cfg.window_border);\r
-    [termview setFrame:rect];\r
-    [[self contentView] addSubview:termview];\r
-\r
-    /*\r
-     * Set up the colour palette.\r
-     */\r
-    palette_reset(self);\r
-\r
-    /*\r
-     * FIXME: Only the _first_ document window should be centred.\r
-     * The subsequent ones should appear down and to the right of\r
-     * it, probably using the cascade function provided by Cocoa.\r
-     * Also we're apparently required by the HIG to remember and\r
-     * reuse previous positions of windows, although I'm not sure\r
-     * how that works if the user opens more than one of the same\r
-     * session type.\r
-     */\r
-    [self center];                    /* :-) */\r
-\r
-    exited = FALSE;\r
-\r
-    return self;\r
-}\r
-\r
-- (void)dealloc\r
-{\r
-    /*\r
-     * FIXME: Here we must deallocate all sorts of stuff: the\r
-     * terminal, the backend, the ldisc, the logctx, you name it.\r
-     * Do so.\r
-     */\r
-    sfree(alert_ctx);\r
-    if (back)\r
-       back->free(backhandle);\r
-    if (ldisc)\r
-       ldisc_free(ldisc);\r
-    /* ldisc must be freed before term, since ldisc_free expects term\r
-     * still to be around. */\r
-    if (logctx)\r
-       log_free(logctx);\r
-    if (term)\r
-       term_free(term);\r
-    [super dealloc];\r
-}\r
-\r
-- (void)drawStartFinish:(BOOL)start\r
-{\r
-    [termview drawStartFinish:start];\r
-}\r
-\r
-- (void)setColour:(int)n r:(float)r g:(float)g b:(float)b\r
-{\r
-    [termview setColour:n r:r g:g b:b];\r
-}\r
-\r
-- (void)doText:(wchar_t *)text len:(int)len x:(int)x y:(int)y\r
-    attr:(unsigned long)attr lattr:(int)lattr\r
-{\r
-    /* Pass this straight on to the TerminalView. */\r
-    [termview doText:text len:len x:x y:y attr:attr lattr:lattr];\r
-}\r
-\r
-- (Config *)cfg\r
-{\r
-    return &cfg;\r
-}\r
-\r
-- (void)keyDown:(NSEvent *)ev\r
-{\r
-    NSString *s = [ev characters];\r
-    int i;\r
-    int n = [s length], c = [s characterAtIndex:0], m = [ev modifierFlags];\r
-    int cm = [[ev charactersIgnoringModifiers] characterAtIndex:0];\r
-    wchar_t output[32];\r
-    char coutput[32];\r
-    int use_coutput = FALSE, special = FALSE, start, end;\r
-\r
-//printf("n=%d c=U+%04x cm=U+%04x m=%08x\n", n, c, cm, m);\r
-\r
-    /*\r
-     * FIXME: Alt+numberpad codes.\r
-     */\r
-\r
-    /*\r
-     * Shift and Ctrl with PageUp/PageDown for scrollback.\r
-     */\r
-    if (n == 1 && c == NSPageUpFunctionKey && (m & NSShiftKeyMask)) {\r
-       term_scroll(term, 0, -term->rows/2);\r
-       return;\r
-    }\r
-    if (n == 1 && c == NSPageUpFunctionKey && (m & NSControlKeyMask)) {\r
-       term_scroll(term, 0, -1);\r
-       return;\r
-    }\r
-    if (n == 1 && c == NSPageDownFunctionKey && (m & NSShiftKeyMask)) {\r
-       term_scroll(term, 0, +term->rows/2);\r
-       return;\r
-    }\r
-    if (n == 1 && c == NSPageDownFunctionKey && (m & NSControlKeyMask)) {\r
-       term_scroll(term, 0, +1);\r
-       return;\r
-    }\r
-\r
-    /*\r
-     * FIXME: Shift-Ins for paste? Or is that not Maccy enough?\r
-     */\r
-\r
-    /*\r
-     * FIXME: Alt (Option? Command?) prefix in general.\r
-     * \r
-     * (Note that Alt-Shift-thing will work just by looking at\r
-     * charactersIgnoringModifiers; but Alt-Ctrl-thing will need\r
-     * processing properly, and Alt-as-in-Option won't happen at\r
-     * all. Hmmm.)\r
-     * \r
-     * (Note also that we need to be able to override menu key\r
-     * equivalents before this is particularly useful.)\r
-     */\r
-    start = 1;\r
-    end = start;\r
-\r
-    /*\r
-     * Ctrl-` is the same as Ctrl-\, unless we already have a\r
-     * better idea.\r
-     */\r
-    if ((m & NSControlKeyMask) && n == 1 && cm == '`' && c == '`') {\r
-       output[1] = '\x1c';\r
-       end = 2;\r
-    }\r
-\r
-    /* We handle Return ourselves, because it needs to be flagged as\r
-     * special to ldisc. */\r
-    if (n == 1 && c == '\015') {\r
-       coutput[1] = '\015';\r
-       use_coutput = TRUE;\r
-       end = 2;\r
-       special = TRUE;\r
-    }\r
-\r
-    /* Control-Shift-Space is 160 (ISO8859 nonbreaking space) */\r
-    if (n == 1 && (m & NSControlKeyMask) && (m & NSShiftKeyMask) &&\r
-       cm == ' ') {\r
-       output[1] = '\240';\r
-       end = 2;\r
-    }\r
-\r
-    /* Control-2, Control-Space and Control-@ are all NUL. */\r
-    if ((m & NSControlKeyMask) && n == 1 &&\r
-       (cm == '2' || cm == '@' || cm == ' ') && c == cm) {\r
-       output[1] = '\0';\r
-       end = 2;\r
-    }\r
-\r
-    /* We don't let MacOS tell us what Backspace is! We know better. */\r
-    if (cm == 0x7F && !(m & NSShiftKeyMask)) {\r
-       coutput[1] = cfg.bksp_is_delete ? '\x7F' : '\x08';\r
-       end = 2;\r
-       use_coutput = special = TRUE;\r
-    }\r
-    /* For Shift Backspace, do opposite of what is configured. */\r
-    if (cm == 0x7F && (m & NSShiftKeyMask)) {\r
-       coutput[1] = cfg.bksp_is_delete ? '\x08' : '\x7F';\r
-       end = 2;\r
-       use_coutput = special = TRUE;\r
-    }\r
-\r
-    /* Shift-Tab is ESC [ Z. Oddly, this combination generates ^Y by\r
-     * default on MacOS! */\r
-    if (cm == 0x19 && (m & NSShiftKeyMask) && !(m & NSControlKeyMask)) {\r
-       end = 1;\r
-       output[end++] = '\033';\r
-       output[end++] = '[';\r
-       output[end++] = 'Z';\r
-    }\r
-\r
-    /*\r
-     * NetHack keypad mode.\r
-     */\r
-    if (cfg.nethack_keypad && (m & NSNumericPadKeyMask)) {\r
-       wchar_t *keys = NULL;\r
-       switch (cm) {\r
-         case '1': keys = L"bB"; break;\r
-         case '2': keys = L"jJ"; break;\r
-         case '3': keys = L"nN"; break;\r
-         case '4': keys = L"hH"; break;\r
-         case '5': keys = L".."; break;\r
-         case '6': keys = L"lL"; break;\r
-         case '7': keys = L"yY"; break;\r
-         case '8': keys = L"kK"; break;\r
-         case '9': keys = L"uU"; break;\r
-       }\r
-       if (keys) {\r
-           end = 2;\r
-           if (m & NSShiftKeyMask)\r
-               output[1] = keys[1];\r
-           else\r
-               output[1] = keys[0];\r
-           goto done;\r
-       }\r
-    }\r
-\r
-    /*\r
-     * Application keypad mode.\r
-     */\r
-    if (term->app_keypad_keys && !cfg.no_applic_k &&\r
-       (m & NSNumericPadKeyMask)) {\r
-       int xkey = 0;\r
-       switch (cm) {\r
-         case NSClearLineFunctionKey: xkey = 'P'; break;\r
-         case '=': xkey = 'Q'; break;\r
-         case '/': xkey = 'R'; break;\r
-         case '*': xkey = 'S'; break;\r
-           /*\r
-            * FIXME: keypad - and + need to be mapped to ESC O l\r
-            * and ESC O k, or ESC O l and ESC O m, depending on\r
-            * xterm function key mode, and I can't remember which\r
-            * goes where.\r
-            */\r
-         case '\003': xkey = 'M'; break;\r
-         case '0': xkey = 'p'; break;\r
-         case '1': xkey = 'q'; break;\r
-         case '2': xkey = 'r'; break;\r
-         case '3': xkey = 's'; break;\r
-         case '4': xkey = 't'; break;\r
-         case '5': xkey = 'u'; break;\r
-         case '6': xkey = 'v'; break;\r
-         case '7': xkey = 'w'; break;\r
-         case '8': xkey = 'x'; break;\r
-         case '9': xkey = 'y'; break;\r
-         case '.': xkey = 'n'; break;\r
-       }\r
-       if (xkey) {\r
-           if (term->vt52_mode) {\r
-               if (xkey >= 'P' && xkey <= 'S') {\r
-                   output[end++] = '\033';\r
-                   output[end++] = xkey;\r
-               } else {\r
-                   output[end++] = '\033';\r
-                   output[end++] = '?';\r
-                   output[end++] = xkey;\r
-               }\r
-           } else {\r
-               output[end++] = '\033';\r
-               output[end++] = 'O';\r
-               output[end++] = xkey;\r
-           }\r
-           goto done;\r
-       }\r
-    }\r
-\r
-    /*\r
-     * Next, all the keys that do tilde codes. (ESC '[' nn '~',\r
-     * for integer decimal nn.)\r
-     *\r
-     * We also deal with the weird ones here. Linux VCs replace F1\r
-     * to F5 by ESC [ [ A to ESC [ [ E. rxvt doesn't do _that_, but\r
-     * does replace Home and End (1~ and 4~) by ESC [ H and ESC O w\r
-     * respectively.\r
-     */\r
-    {\r
-       int code = 0;\r
-       switch (cm) {\r
-         case NSF1FunctionKey:\r
-           code = (m & NSShiftKeyMask ? 23 : 11);\r
-           break;\r
-         case NSF2FunctionKey:\r
-           code = (m & NSShiftKeyMask ? 24 : 12);\r
-           break;\r
-         case NSF3FunctionKey:\r
-           code = (m & NSShiftKeyMask ? 25 : 13);\r
-           break;\r
-         case NSF4FunctionKey:\r
-           code = (m & NSShiftKeyMask ? 26 : 14);\r
-           break;\r
-         case NSF5FunctionKey:\r
-           code = (m & NSShiftKeyMask ? 28 : 15);\r
-           break;\r
-         case NSF6FunctionKey:\r
-           code = (m & NSShiftKeyMask ? 29 : 17);\r
-           break;\r
-         case NSF7FunctionKey:\r
-           code = (m & NSShiftKeyMask ? 31 : 18);\r
-           break;\r
-         case NSF8FunctionKey:\r
-           code = (m & NSShiftKeyMask ? 32 : 19);\r
-           break;\r
-         case NSF9FunctionKey:\r
-           code = (m & NSShiftKeyMask ? 33 : 20);\r
-           break;\r
-         case NSF10FunctionKey:\r
-           code = (m & NSShiftKeyMask ? 34 : 21);\r
-           break;\r
-         case NSF11FunctionKey:\r
-           code = 23;\r
-           break;\r
-         case NSF12FunctionKey:\r
-           code = 24;\r
-           break;\r
-         case NSF13FunctionKey:\r
-           code = 25;\r
-           break;\r
-         case NSF14FunctionKey:\r
-           code = 26;\r
-           break;\r
-         case NSF15FunctionKey:\r
-           code = 28;\r
-           break;\r
-         case NSF16FunctionKey:\r
-           code = 29;\r
-           break;\r
-         case NSF17FunctionKey:\r
-           code = 31;\r
-           break;\r
-         case NSF18FunctionKey:\r
-           code = 32;\r
-           break;\r
-         case NSF19FunctionKey:\r
-           code = 33;\r
-           break;\r
-         case NSF20FunctionKey:\r
-           code = 34;\r
-           break;\r
-       }\r
-       if (!(m & NSControlKeyMask)) switch (cm) {\r
-         case NSHomeFunctionKey:\r
-           code = 1;\r
-           break;\r
-#ifdef FIXME\r
-         case GDK_Insert: case GDK_KP_Insert:\r
-           code = 2;\r
-           break;\r
-#endif\r
-         case NSDeleteFunctionKey:\r
-           code = 3;\r
-           break;\r
-         case NSEndFunctionKey:\r
-           code = 4;\r
-           break;\r
-         case NSPageUpFunctionKey:\r
-           code = 5;\r
-           break;\r
-         case NSPageDownFunctionKey:\r
-           code = 6;\r
-           break;\r
-       }\r
-       /* Reorder edit keys to physical order */\r
-       if (cfg.funky_type == FUNKY_VT400 && code <= 6)\r
-           code = "\0\2\1\4\5\3\6"[code];\r
-\r
-       if (term->vt52_mode && code > 0 && code <= 6) {\r
-           output[end++] = '\033';\r
-           output[end++] = " HLMEIG"[code];\r
-           goto done;\r
-       }\r
-\r
-       if (cfg.funky_type == FUNKY_SCO &&     /* SCO function keys */\r
-           code >= 11 && code <= 34) {\r
-           char codes[] = "MNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@[\\]^_`{";\r
-           int index = 0;\r
-           switch (cm) {\r
-             case NSF1FunctionKey: index = 0; break;\r
-             case NSF2FunctionKey: index = 1; break;\r
-             case NSF3FunctionKey: index = 2; break;\r
-             case NSF4FunctionKey: index = 3; break;\r
-             case NSF5FunctionKey: index = 4; break;\r
-             case NSF6FunctionKey: index = 5; break;\r
-             case NSF7FunctionKey: index = 6; break;\r
-             case NSF8FunctionKey: index = 7; break;\r
-             case NSF9FunctionKey: index = 8; break;\r
-             case NSF10FunctionKey: index = 9; break;\r
-             case NSF11FunctionKey: index = 10; break;\r
-             case NSF12FunctionKey: index = 11; break;\r
-           }\r
-           if (m & NSShiftKeyMask) index += 12;\r
-           if (m & NSControlKeyMask) index += 24;\r
-           output[end++] = '\033';\r
-           output[end++] = '[';\r
-           output[end++] = codes[index];\r
-           goto done;\r
-       }\r
-       if (cfg.funky_type == FUNKY_SCO &&     /* SCO small keypad */\r
-           code >= 1 && code <= 6) {\r
-           char codes[] = "HL.FIG";\r
-           if (code == 3) {\r
-               output[1] = '\x7F';\r
-               end = 2;\r
-           } else {\r
-               output[end++] = '\033';\r
-               output[end++] = '[';\r
-               output[end++] = codes[code-1];\r
-           }\r
-           goto done;\r
-       }\r
-       if ((term->vt52_mode || cfg.funky_type == FUNKY_VT100P) &&\r
-           code >= 11 && code <= 24) {\r
-           int offt = 0;\r
-           if (code > 15)\r
-               offt++;\r
-           if (code > 21)\r
-               offt++;\r
-           if (term->vt52_mode) {\r
-               output[end++] = '\033';\r
-               output[end++] = code + 'P' - 11 - offt;\r
-           } else {\r
-               output[end++] = '\033';\r
-               output[end++] = 'O';\r
-               output[end++] = code + 'P' - 11 - offt;\r
-           }\r
-           goto done;\r
-       }\r
-       if (cfg.funky_type == FUNKY_LINUX && code >= 11 && code <= 15) {\r
-           output[end++] = '\033';\r
-           output[end++] = '[';\r
-           output[end++] = '[';        \r
-           output[end++] = code + 'A' - 11;\r
-           goto done;\r
-       }\r
-       if (cfg.funky_type == FUNKY_XTERM && code >= 11 && code <= 14) {\r
-           if (term->vt52_mode) {\r
-               output[end++] = '\033';\r
-               output[end++] = code + 'P' - 11;\r
-           } else {\r
-               output[end++] = '\033';\r
-               output[end++] = 'O';\r
-               output[end++] = code + 'P' - 11;\r
-           }\r
-           goto done;\r
-       }\r
-       if (cfg.rxvt_homeend && (code == 1 || code == 4)) {\r
-           if (code == 1) {\r
-               output[end++] = '\033';\r
-               output[end++] = '[';\r
-               output[end++] = 'H';\r
-           } else {\r
-               output[end++] = '\033';\r
-               output[end++] = 'O';\r
-               output[end++] = 'w';\r
-           }\r
-           goto done;\r
-       }\r
-       if (code) {\r
-           char buf[20];\r
-           sprintf(buf, "\x1B[%d~", code);\r
-           for (i = 0; buf[i]; i++)\r
-               output[end++] = buf[i];\r
-           goto done;\r
-       }\r
-    }\r
-\r
-    /*\r
-     * Cursor keys. (This includes the numberpad cursor keys,\r
-     * if we haven't already done them due to app keypad mode.)\r
-     */\r
-    {\r
-       int xkey = 0;\r
-       switch (cm) {\r
-         case NSUpArrowFunctionKey: xkey = 'A'; break;\r
-         case NSDownArrowFunctionKey: xkey = 'B'; break;\r
-         case NSRightArrowFunctionKey: xkey = 'C'; break;\r
-         case NSLeftArrowFunctionKey: xkey = 'D'; break;\r
-       }\r
-       if (xkey) {\r
-           end += format_arrow_key(output+end, term, xkey,\r
-                                   m & NSControlKeyMask);\r
-           goto done;\r
-       }\r
-    }\r
-\r
-    done:\r
-\r
-    /*\r
-     * Failing everything else, send the exact Unicode we got from\r
-     * OS X.\r
-     */\r
-    if (end == start) {\r
-       if (n > lenof(output)-start)\r
-           n = lenof(output)-start;   /* _shouldn't_ happen! */\r
-       for (i = 0; i < n; i++) {\r
-           output[i+start] = [s characterAtIndex:i];\r
-       }\r
-       end = n+start;\r
-    }\r
-\r
-    if (use_coutput) {\r
-       assert(special);\r
-       assert(end < lenof(coutput));\r
-       coutput[end] = '\0';\r
-       ldisc_send(ldisc, coutput+start, -2, TRUE);\r
-    } else {\r
-       luni_send(ldisc, output+start, end-start, TRUE);\r
-    }\r
-}\r
-\r
-- (int)fromBackend:(const char *)data len:(int)len isStderr:(int)is_stderr\r
-{\r
-    return term_data(term, is_stderr, data, len);\r
-}\r
-\r
-- (int)fromBackendUntrusted:(const char *)data len:(int)len\r
-{\r
-    return term_data_untrusted(term, data, len);\r
-}\r
-\r
-- (void)startAlert:(NSAlert *)alert\r
-    withCallback:(void (*)(void *, int))callback andCtx:(void *)ctx\r
-{\r
-    if (alert_ctx || alert_qhead) {\r
-       /*\r
-        * Queue this alert to be shown later.\r
-        */\r
-       struct alert_queue *qitem = snew(struct alert_queue);\r
-       qitem->next = NULL;\r
-       qitem->alert = alert;\r
-       qitem->callback = callback;\r
-       qitem->ctx = ctx;\r
-       if (alert_qtail)\r
-           alert_qtail->next = qitem;\r
-       else\r
-           alert_qhead = qitem;\r
-       alert_qtail = qitem;\r
-    } else {\r
-       alert_callback = callback;\r
-       alert_ctx = ctx;               /* NB this is assumed to need freeing! */\r
-       [alert beginSheetModalForWindow:self modalDelegate:self\r
-        didEndSelector:@selector(alertSheetDidEnd:returnCode:contextInfo:)\r
-        contextInfo:NULL];\r
-    }\r
-}\r
-\r
-- (void)alertSheetDidEnd:(NSAlert *)alert returnCode:(int)returnCode\r
-    contextInfo:(void *)contextInfo\r
-{\r
-    [self performSelectorOnMainThread:\r
-     @selector(alertSheetDidFinishEnding:)\r
-     withObject:[NSNumber numberWithInt:returnCode]\r
-     waitUntilDone:NO];\r
-}\r
-\r
-- (void)alertSheetDidFinishEnding:(id)object\r
-{\r
-    int returnCode = [object intValue];\r
-\r
-    alert_callback(alert_ctx, returnCode);   /* transfers ownership of ctx */\r
-\r
-    /*\r
-     * If there's an alert in our queue (either already or because\r
-     * the callback just queued it), start it.\r
-     */\r
-    if (alert_qhead) {\r
-       struct alert_queue *qnext;\r
-\r
-       alert_callback = alert_qhead->callback;\r
-       alert_ctx = alert_qhead->ctx;\r
-       [alert_qhead->alert beginSheetModalForWindow:self modalDelegate:self\r
-        didEndSelector:@selector(alertSheetDidEnd:returnCode:contextInfo:)\r
-        contextInfo:NULL];\r
-\r
-       qnext = alert_qhead->next;\r
-       sfree(alert_qhead);\r
-       alert_qhead = qnext;\r
-       if (!qnext)\r
-           alert_qtail = NULL;\r
-    } else {\r
-       alert_ctx = NULL;\r
-    }\r
-}\r
-\r
-- (void)notifyRemoteExit\r
-{\r
-    int exitcode;\r
-\r
-    if (!exited && (exitcode = back->exitcode(backhandle)) >= 0)\r
-       [self endSession:(exitcode == 0)];\r
-}\r
-\r
-- (void)endSession:(int)clean\r
-{\r
-    exited = TRUE;\r
-    if (ldisc) {\r
-       ldisc_free(ldisc);\r
-       ldisc = NULL;\r
-    }\r
-    if (back) {\r
-       back->free(backhandle);\r
-       backhandle = NULL;\r
-       back = NULL;\r
-       //FIXME: update specials menu;\r
-    }\r
-    if (cfg.close_on_exit == FORCE_ON ||\r
-       (cfg.close_on_exit == AUTO && clean))\r
-       [self close];\r
-    // FIXME: else show restart menu item\r
-}\r
-\r
-- (Terminal *)term\r
-{\r
-    return term;\r
-}\r
-\r
-@end\r
-\r
-int from_backend(void *frontend, int is_stderr, const char *data, int len)\r
-{\r
-    SessionWindow *win = (SessionWindow *)frontend;\r
-    return [win fromBackend:data len:len isStderr:is_stderr];\r
-}\r
-\r
-int from_backend_untrusted(void *frontend, const char *data, int len)\r
-{\r
-    SessionWindow *win = (SessionWindow *)frontend;\r
-    return [win fromBackendUntrusted:data len:len];\r
-}\r
-\r
-int get_userpass_input(prompts_t *p, unsigned char *in, int inlen)\r
-{\r
-    SessionWindow *win = (SessionWindow *)p->frontend;\r
-    Terminal *term = [win term];\r
-    return term_get_userpass_input(term, p, in, inlen);\r
-}\r
-\r
-void frontend_keypress(void *handle)\r
-{\r
-    /* FIXME */\r
-}\r
-\r
-void notify_remote_exit(void *frontend)\r
-{\r
-    SessionWindow *win = (SessionWindow *)frontend;\r
-\r
-    [win notifyRemoteExit];\r
-}\r
-\r
-void ldisc_update(void *frontend, int echo, int edit)\r
-{\r
-    //SessionWindow *win = (SessionWindow *)frontend;\r
-    /*\r
-     * In a GUI front end, this need do nothing.\r
-     */\r
-}\r
-\r
-char *get_ttymode(void *frontend, const char *mode)\r
-{\r
-    SessionWindow *win = (SessionWindow *)frontend;\r
-    Terminal *term = [win term];\r
-    return term_get_ttymode(term, mode);\r
-}\r
-\r
-void update_specials_menu(void *frontend)\r
-{\r
-    //SessionWindow *win = (SessionWindow *)frontend;\r
-    /* FIXME */\r
-}\r
-\r
-/*\r
- * This is still called when mode==BELL_VISUAL, even though the\r
- * visual bell is handled entirely within terminal.c, because we\r
- * may want to perform additional actions on any kind of bell (for\r
- * example, taskbar flashing in Windows).\r
- */\r
-void do_beep(void *frontend, int mode)\r
-{\r
-    //SessionWindow *win = (SessionWindow *)frontend;\r
-    if (mode != BELL_VISUAL)\r
-       NSBeep();\r
-}\r
-\r
-int char_width(Context ctx, int uc)\r
-{\r
-    /*\r
-     * Under X, any fixed-width font really _is_ fixed-width.\r
-     * Double-width characters will be dealt with using a separate\r
-     * font. For the moment we can simply return 1.\r
-     */\r
-    return 1;\r
-}\r
-\r
-void palette_set(void *frontend, int n, int r, int g, int b)\r
-{\r
-    SessionWindow *win = (SessionWindow *)frontend;\r
-\r
-    if (n >= 16)\r
-       n += 256 - 16;\r
-    if (n > NALLCOLOURS)\r
-       return;\r
-    [win setColour:n r:r/255.0 g:g/255.0 b:b/255.0];\r
-\r
-    /*\r
-     * FIXME: do we need an OS X equivalent of set_window_background?\r
-     */\r
-}\r
-\r
-void palette_reset(void *frontend)\r
-{\r
-    SessionWindow *win = (SessionWindow *)frontend;\r
-    Config *cfg = [win cfg];\r
-\r
-    /* This maps colour indices in cfg to those used in colours[]. */\r
-    static const int ww[] = {\r
-       256, 257, 258, 259, 260, 261,\r
-       0, 8, 1, 9, 2, 10, 3, 11,\r
-       4, 12, 5, 13, 6, 14, 7, 15\r
-    };\r
-\r
-    int i;\r
-\r
-    for (i = 0; i < NCFGCOLOURS; i++) {\r
-       [win setColour:ww[i] r:cfg->colours[i][0]/255.0\r
-        g:cfg->colours[i][1]/255.0 b:cfg->colours[i][2]/255.0];\r
-    }\r
-\r
-    for (i = 0; i < NEXTCOLOURS; i++) {\r
-       if (i < 216) {\r
-           int r = i / 36, g = (i / 6) % 6, b = i % 6;\r
-           r = r ? r*40+55 : 0; g = g ? b*40+55 : 0; b = b ? b*40+55 : 0;\r
-           [win setColour:i+16 r:r/255.0 g:g/255.0 b:b/255.0];\r
-       } else {\r
-           int shade = i - 216;\r
-           float fshade = (shade * 10 + 8) / 255.0;\r
-           [win setColour:i+16 r:fshade g:fshade b:fshade];\r
-       }\r
-    }\r
-\r
-    /*\r
-     * FIXME: do we need an OS X equivalent of set_window_background?\r
-     */\r
-}\r
-\r
-Context get_ctx(void *frontend)\r
-{\r
-    SessionWindow *win = (SessionWindow *)frontend;\r
-\r
-    /*\r
-     * Lock the drawing focus on the image inside the TerminalView.\r
-     */\r
-    [win drawStartFinish:YES];\r
-\r
-    [[NSGraphicsContext currentContext] setShouldAntialias:YES];\r
-\r
-    /*\r
-     * Cocoa drawing functions don't take a graphics context: that\r
-     * parameter is implicit. Therefore, we'll use the frontend\r
-     * handle itself as the context, on the grounds that it's as\r
-     * good a thing to use as any.\r
-     */\r
-    return frontend;\r
-}\r
-\r
-void free_ctx(Context ctx)\r
-{\r
-    SessionWindow *win = (SessionWindow *)ctx;\r
-\r
-    [win drawStartFinish:NO];\r
-}\r
-\r
-void do_text(Context ctx, int x, int y, wchar_t *text, int len,\r
-            unsigned long attr, int lattr)\r
-{\r
-    SessionWindow *win = (SessionWindow *)ctx;\r
-\r
-    [win doText:text len:len x:x y:y attr:attr lattr:lattr];\r
-}\r
-\r
-void do_cursor(Context ctx, int x, int y, wchar_t *text, int len,\r
-              unsigned long attr, int lattr)\r
-{\r
-    SessionWindow *win = (SessionWindow *)ctx;\r
-    Config *cfg = [win cfg];\r
-    int active, passive;\r
-\r
-    if (attr & TATTR_PASCURS) {\r
-       attr &= ~TATTR_PASCURS;\r
-       passive = 1;\r
-    } else\r
-       passive = 0;\r
-    if ((attr & TATTR_ACTCURS) && cfg->cursor_type != 0) {\r
-       attr &= ~TATTR_ACTCURS;\r
-        active = 1;\r
-    } else\r
-        active = 0;\r
-\r
-    [win doText:text len:len x:x y:y attr:attr lattr:lattr];\r
-\r
-    /*\r
-     * FIXME: now draw the various cursor types (both passive and\r
-     * active underlines and vertical lines, plus passive blocks).\r
-     */\r
-}\r
-\r
-/*\r
- * Minimise or restore the window in response to a server-side\r
- * request.\r
- */\r
-void set_iconic(void *frontend, int iconic)\r
-{\r
-    //SessionWindow *win = (SessionWindow *)frontend;\r
-    /* FIXME */\r
-}\r
-\r
-/*\r
- * Move the window in response to a server-side request.\r
- */\r
-void move_window(void *frontend, int x, int y)\r
-{\r
-    //SessionWindow *win = (SessionWindow *)frontend; \r
-    /* FIXME */\r
-}\r
-\r
-/*\r
- * Move the window to the top or bottom of the z-order in response\r
- * to a server-side request.\r
- */\r
-void set_zorder(void *frontend, int top)\r
-{\r
-    //SessionWindow *win = (SessionWindow *)frontend;\r
-    /* FIXME */\r
-}\r
-\r
-/*\r
- * Refresh the window in response to a server-side request.\r
- */\r
-void refresh_window(void *frontend)\r
-{\r
-    //SessionWindow *win = (SessionWindow *)frontend;\r
-    /* FIXME */\r
-}\r
-\r
-/*\r
- * Maximise or restore the window in response to a server-side\r
- * request.\r
- */\r
-void set_zoomed(void *frontend, int zoomed)\r
-{\r
-    //SessionWindow *win = (SessionWindow *)frontend;\r
-    /* FIXME */\r
-}\r
-\r
-/*\r
- * Report whether the window is iconic, for terminal reports.\r
- */\r
-int is_iconic(void *frontend)\r
-{\r
-    //SessionWindow *win = (SessionWindow *)frontend;\r
-    return NO;                                /* FIXME */\r
-}\r
-\r
-/*\r
- * Report the window's position, for terminal reports.\r
- */\r
-void get_window_pos(void *frontend, int *x, int *y)\r
-{\r
-    //SessionWindow *win = (SessionWindow *)frontend;\r
-    /* FIXME */\r
-}\r
-\r
-/*\r
- * Report the window's pixel size, for terminal reports.\r
- */\r
-void get_window_pixels(void *frontend, int *x, int *y)\r
-{\r
-    //SessionWindow *win = (SessionWindow *)frontend;\r
-    /* FIXME */\r
-}\r
-\r
-/*\r
- * Return the window or icon title.\r
- */\r
-char *get_window_title(void *frontend, int icon)\r
-{\r
-    //SessionWindow *win = (SessionWindow *)frontend;\r
-    return NULL; /* FIXME */\r
-}\r
-\r
-void set_title(void *frontend, char *title)\r
-{\r
-    //SessionWindow *win = (SessionWindow *)frontend;\r
-    /* FIXME */\r
-}\r
-\r
-void set_icon(void *frontend, char *title)\r
-{\r
-    //SessionWindow *win = (SessionWindow *)frontend;\r
-    /* FIXME */\r
-}\r
-\r
-void set_sbar(void *frontend, int total, int start, int page)\r
-{\r
-    //SessionWindow *win = (SessionWindow *)frontend;\r
-    /* FIXME */\r
-}\r
-\r
-void get_clip(void *frontend, wchar_t ** p, int *len)\r
-{\r
-    //SessionWindow *win = (SessionWindow *)frontend;\r
-    /* FIXME */\r
-}\r
-\r
-void write_clip(void *frontend, wchar_t *data, int *attr, int len, int must_deselect)\r
-{\r
-    //SessionWindow *win = (SessionWindow *)frontend;\r
-    /* FIXME */\r
-}\r
-\r
-void request_paste(void *frontend)\r
-{\r
-    //SessionWindow *win = (SessionWindow *)frontend;\r
-    /* FIXME */\r
-}\r
-\r
-void set_raw_mouse_mode(void *frontend, int activate)\r
-{\r
-    //SessionWindow *win = (SessionWindow *)frontend;\r
-    /* FIXME */\r
-}\r
-\r
-void request_resize(void *frontend, int w, int h)\r
-{\r
-    //SessionWindow *win = (SessionWindow *)frontend;\r
-    /* FIXME */\r
-}\r
-\r
-void sys_cursor(void *frontend, int x, int y)\r
-{\r
-    //SessionWindow *win = (SessionWindow *)frontend;\r
-    /*\r
-     * This is probably meaningless under OS X. FIXME: find out for\r
-     * sure.\r
-     */\r
-}\r
-\r
-void logevent(void *frontend, const char *string)\r
-{\r
-    //SessionWindow *win = (SessionWindow *)frontend;\r
-    /* FIXME */\r
-printf("logevent: %s\n", string);\r
-}\r
-\r
-int font_dimension(void *frontend, int which)/* 0 for width, 1 for height */\r
-{\r
-    //SessionWindow *win = (SessionWindow *)frontend;\r
-    return 1; /* FIXME */\r
-}\r
-\r
-void set_busy_status(void *frontend, int status)\r
-{\r
-    /*\r
-     * We need do nothing here: the OS X `application is busy'\r
-     * beachball pointer appears _automatically_ when the\r
-     * application isn't responding to GUI messages.\r
-     */\r
-}\r