]> asedeno.scripts.mit.edu Git - PuTTY.git/commitdiff
Delete the old 'macosx' directory completely.
authorSimon Tatham <anakin@pobox.com>
Fri, 25 Mar 2016 09:06:03 +0000 (09:06 +0000)
committerSimon Tatham <anakin@pobox.com>
Fri, 25 Mar 2016 09:06:03 +0000 (09:06 +0000)
The current state of the OS X GTK port is looking more or less
plausible - it's not finished, of course, but then neither was the old
native Cocoa port. So I'm inclined to advertise it as *the* unfinished
OS X port: it's the one I intend to keep working on, and it's the one
I'd prefer people offered us help with if they're going to offer.

Hence, leaving the old macosx directory around is just confusing; that
directory is long-unmaintained, probably doesn't even compile, and its
only effect will be to mislead people into thinking it's still
relevant. I'm unilaterally deleting it; of course we can always
recover it from source control history if it's ever necessary to do
so.

12 files changed:
.gitignore
Recipe
macosx/README.OSX [deleted file]
macosx/info.plist [deleted file]
macosx/osx.h [deleted file]
macosx/osxclass.h [deleted file]
macosx/osxctrls.m [deleted file]
macosx/osxdlg.m [deleted file]
macosx/osxmain.m [deleted file]
macosx/osxsel.m [deleted file]
macosx/osxwin.m [deleted file]
puttyps.h

index 25851bf6c09943b822a4811c8527d3795492f6df..bbb2cc09f1cec4b7952fadab0bd19b7375da4b84 100644 (file)
 /icons/*.icns
 /icons/*.xpm
 /icons/*.c
-/macosx/Makefile
-/macosx/*.app
-/macosx/puttygen
-/macosx/plink
-/macosx/psftp
-/macosx/pscp
 /testdata/bignum.txt
 /unix/Makefile.gtk
 /unix/Makefile.ux
diff --git a/Recipe b/Recipe
index e8801da59bd59992a562d70cf197acebec5a5cea..52fe3f4e2581b0a0b2349bcd4d8b6d5ba2832824 100644 (file)
--- a/Recipe
+++ b/Recipe
@@ -20,7 +20,6 @@
 !makefile gtk unix/Makefile.gtk
 !makefile unix unix/Makefile.ux
 !makefile am Makefile.am
-!makefile osx macosx/Makefile
 !makefile devcppproj windows/DEVCPP
 !makefile vstudio10 windows/VS2010
 !makefile vstudio12 windows/VS2012
@@ -28,7 +27,6 @@
 !srcdir charset/
 !srcdir windows/
 !srcdir unix/
-!srcdir macosx/
 
 # Help text added to the top of each Makefile, with /D converted
 # into -D as appropriate for the particular Makefile.
@@ -173,9 +171,6 @@ install:
 install-strip:
        $(MAKE) install INSTALL_PROGRAM="$(INSTALL_PROGRAM) -s"
 !end
-!begin osx vars
-CFLAGS += -DMACOSX
-!end
 
 # List the man pages for the automake makefile.
 !begin am
@@ -231,7 +226,6 @@ GUITERM  = TERMINAL window windlg winctrls sizetip winucs winprint
 UXTERM   = TERMINAL uxcfg sercfg uxucs uxprint timing callback miscucs
 GTKTERM  = UXTERM gtkwin gtkcfg gtkdlg gtkfont gtkcols gtkmisc xkeysym
         + x11misc gtkcomm
-OSXTERM  = UXTERM osxwin osxdlg osxctrls
 
 # Non-SSH back ends (putty, puttytel, plink).
 NONSSH   = telnet raw rlogin ldisc pinger
@@ -254,7 +248,6 @@ MISC     = timing callback misc version settings tree234 proxy conf be_misc
 WINMISC  = MISC winstore winnet winhandl cmdline windefs winmisc winproxy
          + wintime winhsock errsock winsecur
 UXMISC   = MISC uxstore uxsel uxnet uxpeer cmdline uxmisc uxproxy time
-OSXMISC  = MISC uxstore uxsel osxsel uxnet uxpeer uxmisc uxproxy time
 
 # import.c and dependencies, for PuTTYgen-like utilities that have to
 # load foreign key files.
@@ -331,9 +324,6 @@ pageant  : [X] uxpgnt uxagentc pageant sshrsa sshpubk sshdes sshbn sshmd5
         + conf uxsignal nocproxy nogss be_none x11fwd ux_x11 uxcons gtkask
         + gtkmisc UXMISC
 
-PuTTY    : [MX] osxmain OSXTERM OSXMISC CHARSET U_BE_ALL NONSSH UXSSH
-         + ux_x11 uxpty uxsignal testback putty.icns info.plist
-
 ptermapp : [XT] GTKTERM uxmisc misc ldisc settings uxpty uxsel BE_NONE uxstore
          + uxsignal CHARSET cmdline uxpterm version time xpmpterm xpmptcfg
          + nogss gtkapp
diff --git a/macosx/README.OSX b/macosx/README.OSX
deleted file mode 100644 (file)
index 084671a..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-This directory contains a Mac OS X port of PuTTY/pterm, running as a
-native Aqua GUI application.
-
-THIS PORT IS CURRENTLY UNFINISHED AND EXPERIMENTAL. It is _not_
-considered to be of release quality, even if you've found it (and
-are reading this) in a PuTTY release source archive. You are welcome
-to try using it, but don't be surprised at unexpected behaviour. I'm
-not kidding.
-
-In particular, I have not yet decided where OS X PuTTY should store
-its configuration data. Options include storing it in ~/.putty to be
-compatible with Unix PuTTY, storing it wherever is compatible with
-Mac Classic PuTTY, storing it in a natively OS X location, or
-sorting out the `config-locations' wishlist item and doing all
-three. Therefore, if you start using this port and create a whole
-load of saved sessions, you should not be surprised if a future
-version of the port decides to look somewhere completely different
-for the data and therefore loses them all. If that happens, don't
-say you weren't warned!
-
-Other ways in which the port is currently unfinished include:
-
-Bit rot
--------
-
- - the conversion of the old fixed-size 'Config' structure to the
-   new dynamic 'Conf' was never applied to this directory
-
- - probably other things are out of date too; it would need some
-   work to make it compile again
-
-Missing terminal window features
---------------------------------
-
- - terminal display is horribly slow
-
- - fonts aren't configurable
-
- - several features are unimplemented in the terminal display:
-   underlining, non-solid-block cursors, double-width and
-   double-height line attributes, bold as font rather than as
-   colour, wide (CJK) characters, combining characters.
-
- - there's no scrollbar
-
- - terminal window resizing isn't implemented yet
-
- - proper window placement (cascading down and right from the
-   starting position, plus remembering previous window positions per
-   the Apple HIG) is not implemented
-
-Missing alert box features
---------------------------
-
- - warn-on-close isn't implemented
-
-Missing input features
-----------------------
-
- - use of Alt+numberpad to enter arbitrary numeric character codes
-   is not yet supported
-
- - there's no Meta key yet. (I'd like to at least have the
-   possibility of using Command rather than Option as the Meta key,
-   since the latter is necessary to send some characters, including
-   the rather important # on Apple UK keyboards; but trapping
-   Command-<key> and sending it to the window rather than the
-   application menu requires me to make a positive effort of some
-   sort and I haven't got round to it yet. For those Mac users who
-   consider their Command key sacrosanct, don't worry, this option
-   _will_ be configurable and _will_ be off by default.)
-
- - there's no specials menu
-
- - mouse activity isn't supported (neither cut-and-paste nor xterm
-   mouse tracking)
-
-Missing terminal emulation features
------------------------------------
-
- - currently no support for server-side window management requests
-   (i.e. escape sequences to minimise or maximise the window,
-   request or change its position and size, change its title etc)
-
- - window title is currently fixed
-
-Other missing features
-----------------------
-
- - no Event Log
-
- - no mid-session Change Settings
diff --git a/macosx/info.plist b/macosx/info.plist
deleted file mode 100644 (file)
index ce03a33..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-       <key>CFBundleIconFile</key>
-       <string>PuTTY.icns</string>
-</dict>
-</plist>
diff --git a/macosx/osx.h b/macosx/osx.h
deleted file mode 100644 (file)
index 165539f..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef PUTTY_OSX_H
-#define PUTTY_OSX_H
-
-/*
- * Cocoa defines `FontSpec' itself, so we must change its name.
- * (Arrgh.)
- */
-#define FontSpec FontSpec_OSX_Proof
-
-/*
- * Define the various compatibility symbols to make uxpty.c compile
- * correctly on OS X.
- */
-#define BSD_PTYS
-#define OMIT_UTMP
-#define HAVE_NO_SETRESUID
-#define NOT_X_WINDOWS
-
-/*
- * OS X is largely just Unix, so we can include most of this
- * unchanged.
- */
-#include "unix.h"
-
-/*
- * Functions exported by osxsel.m. (Both of these functions are
- * expected to be called in the _main_ thread: the select subthread
- * is an implementation detail of osxsel.m and ideally should not
- * be visible at all outside it.)
- */
-void osxsel_init(void);                       /* call this to kick things off */
-void osxsel_process_results(void);     /* call this on receipt of a netevent */
-
-#endif
diff --git a/macosx/osxclass.h b/macosx/osxclass.h
deleted file mode 100644 (file)
index e79290d..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Header file for the Objective-C parts of Mac OS X PuTTY. This
- * file contains the class definitions, which would cause compile
- * failures in the pure C modules if they appeared in osx.h.
- */
-
-#ifndef PUTTY_OSXCLASS_H
-#define PUTTY_OSXCLASS_H
-
-#include "putty.h"
-
-/*
- * The application controller class, defined in osxmain.m.
- */
-@interface AppController : NSObject
-{
-    NSTimer *timer;
-}
-- (void)newSessionConfig:(id)sender;
-- (void)newTerminal:(id)sender;
-- (void)newSessionWithConfig:(id)cfg;
-- (void)setTimer:(long)next;
-@end
-extern AppController *controller;
-
-/*
- * The SessionWindow class, defined in osxwin.m.
- */
-
-struct alert_queue {
-    struct alert_queue *next;
-    NSAlert *alert;
-    void (*callback)(void *, int);
-    void *ctx;
-};
-
-@class SessionWindow;
-@class TerminalView;
-
-@interface SessionWindow : NSWindow
-{
-    Terminal *term;
-    TerminalView *termview;
-    struct unicode_data ucsdata;
-    void *logctx;
-    Config cfg;
-    void *ldisc;
-    Backend *back;
-    void *backhandle;
-    int exited;
-    /*
-     * The following two members relate to the currently active
-     * alert sheet, if any. They are NULL if there isn't one.
-     */
-    void (*alert_callback)(void *, int);
-    void *alert_ctx;
-    /* This queues future alerts that need to be shown. */
-    struct alert_queue *alert_qhead, *alert_qtail;
-}
-- (id)initWithConfig:(Config)cfg;
-- (void)drawStartFinish:(BOOL)start;
-- (void)setColour:(int)n r:(float)r g:(float)g b:(float)b;
-- (Config *)cfg;
-- (void)doText:(wchar_t *)text len:(int)len x:(int)x y:(int)y
-    attr:(unsigned long)attr lattr:(int)lattr;
-- (int)fromBackend:(const char *)data len:(int)len isStderr:(int)is_stderr;
-- (int)fromBackendUntrusted:(const char *)data len:(int)len;
-- (void)startAlert:(NSAlert *)alert
-    withCallback:(void (*)(void *, int))callback andCtx:(void *)ctx;
-- (void)endSession:(int)clean;
-- (void)notifyRemoteExit;
-- (Terminal *)term;
-@end
-
-/*
- * The ConfigWindow class, defined in osxdlg.m.
- */
-
-@class ConfigWindow;
-
-@interface ConfigWindow : NSWindow
-{
-    NSOutlineView *treeview;
-    struct controlbox *ctrlbox;
-    void *dv;
-    Config cfg;
-}
-- (id)initWithConfig:(Config)cfg;
-@end
-
-/*
- * Functions exported by osxctrls.m. (They have to go in this
- * header file and not osx.h, because some of them have Cocoa class
- * types in their prototypes.)
- */
-#define HSPACING 12                   /* needed in osxdlg.m and osxctrls.m */
-#define VSPACING 8
-
-void *fe_dlg_init(void *data, NSWindow *window, NSObject *target, SEL action);
-void fe_dlg_free(void *dv);
-void create_ctrls(void *dv, NSView *parent, struct controlset *s,
-                 int *minw, int *minh);
-int place_ctrls(void *dv, struct controlset *s, int leftx, int topy,
-               int width);            /* returns height used */
-void select_panel(void *dv, struct controlbox *b, const char *name);
-
-#endif /* PUTTY_OSXCLASS_H */
diff --git a/macosx/osxctrls.m b/macosx/osxctrls.m
deleted file mode 100644 (file)
index 27c2c52..0000000
+++ /dev/null
@@ -1,1781 +0,0 @@
-/*
- * osxctrls.m: OS X implementation of the dialog.h interface.
- */
-
-#import <Cocoa/Cocoa.h>
-#include "putty.h"
-#include "dialog.h"
-#include "osxclass.h"
-#include "tree234.h"
-
-/*
- * Still to be implemented:
- * 
- *  - file selectors (NSOpenPanel / NSSavePanel)
- * 
- *  - font selectors
- *  - colour selectors
- *     * both of these have a conceptual oddity in Cocoa that
- *      you're only supposed to have one per application. But I
- *      currently expect to be able to have multiple PuTTY config
- *      boxes on screen at once; what happens if you trigger the
- *      font selector in each one at the same time?
- *     * if it comes to that, the _font_ selector can probably be
- *      managed by other means: nobody is forcing me to implement
- *      a font selector using a `Change...' button. The portable
- *      dialog interface gives me the flexibility to do this how I
- *      want.
- *     * The colour selector interface, in its present form, is
- *      more interesting and _if_ a radical change of plan is
- *      required then it may stretch across the interface into the
- *      portable side.
- *     * Before I do anything rash I should start by looking at the
- *      Mac Classic port and see how it's done there, on the basis
- *      that Apple seem reasonably unlikely to have invented this
- *      crazy restriction specifically for OS X.
- * 
- *  - focus management
- *     * I tried using makeFirstResponder to give keyboard focus,
- *      but it appeared not to work. Try again, and work out how
- *      it should be done.
- *     * also look into tab order. Currently pressing Tab suggests
- *      that only edit boxes and list boxes can get the keyboard
- *      focus, and that buttons (in all their forms) are unable to
- *      be driven by the keyboard. Find out for sure.
- * 
- *  - dlg_error_msg
- *     * this may run into the usual aggro with modal dialog boxes.
- */
-
-/*
- * For Cocoa control layout, I need a two-stage process. In stage
- * one, I allocate all the controls and measure their natural
- * sizes, which allows me to compute the _minimum_ width and height
- * of a given section of dialog. Then, in stage two, I lay out the
- * dialog box as a whole, decide how much each section of the box
- * needs to receive, and assign it its final size.
- */
-
-/*
- * As yet unsolved issues [FIXME]:
- * 
- *  - Sometimes the height returned from create_ctrls and the
- *    height returned from place_ctrls differ. Find out why. It may
- *    be harmless (e.g. results of NSTextView being odd), but I
- *    want to know.
- * 
- *  - NSTextViews are indented a bit. It'd be nice to put their
- *    left margin at the same place as everything else's.
- * 
- *  - I don't yet know whether we even _can_ support tab order or
- *    keyboard shortcuts. If we can't, then fair enough, we can't.
- *    But if we can, we should.
- * 
- *  - I would _really_ like to know of a better way to correct
- *    NSButton's stupid size estimates than by subclassing it and
- *    overriding sizeToFit with hard-wired sensible values!
- * 
- *  - Speaking of stupid size estimates, the amount by which I'm
- *    adjusting a titled NSBox (currently equal to the point size
- *    of its title font) looks as if it isn't _quite_ enough.
- *    Figure out what the real amount should be and use it.
- * 
- *  - I don't understand why there's always a scrollbar displayed
- *    in each list box. I thought I told it to autohide scrollers?
- * 
- *  - Why do I have to fudge list box heights by adding one? (Might
- *    it be to do with the missing header view?)
- */
-
-/*
- * Subclass of NSButton which corrects the fact that the normal
- * one's sizeToFit method persistently returns 32 as its height,
- * which is simply a lie. I have yet to work out a better
- * alternative than hard-coding the real heights.
- */
-@interface MyButton : NSButton
-{
-    int minht;
-}
-@end
-@implementation MyButton
-- (id)initWithFrame:(NSRect)r
-{
-    self = [super initWithFrame:r];
-    minht = 25;
-    return self;
-}
-- (void)setButtonType:(NSButtonType)t
-{
-    if (t == NSRadioButton || t == NSSwitchButton)
-       minht = 18;
-    else
-       minht = 25;
-    [super setButtonType:t];
-}
-- (void)sizeToFit
-{
-    NSRect r;
-    [super sizeToFit];
-    r = [self frame];
-    r.size.height = minht;
-    [self setFrame:r];
-}
-@end
-
-/*
- * Class used as the data source for NSTableViews.
- */
-@interface MyTableSource : NSObject
-{
-    tree234 *tree;
-}
-- (id)init;
-- (void)add:(const char *)str withId:(int)id;
-- (int)getid:(int)index;
-- (void)swap:(int)index1 with:(int)index2;
-- (void)removestr:(int)index;
-- (void)clear;
-@end
-@implementation MyTableSource
-- (id)init
-{
-    self = [super init];
-    tree = newtree234(NULL);
-    return self;
-}
-- (void)dealloc
-{
-    char *p;
-    while ((p = delpos234(tree, 0)) != NULL)
-       sfree(p);
-    freetree234(tree);
-    [super dealloc];
-}
-- (void)add:(const char *)str withId:(int)id
-{
-    addpos234(tree, dupprintf("%d\t%s", id, str), count234(tree));
-}
-- (int)getid:(int)index
-{
-    char *p = index234(tree, index);
-    return atoi(p);
-}
-- (void)removestr:(int)index
-{
-    char *p = delpos234(tree, index);
-    sfree(p);
-}
-- (void)swap:(int)index1 with:(int)index2
-{
-    char *p1, *p2;
-
-    if (index1 > index2) {
-       int t = index1; index1 = index2; index2 = t;
-    }
-
-    /* delete later one first so it doesn't affect index of earlier one */
-    p2 = delpos234(tree, index2);
-    p1 = delpos234(tree, index1);
-
-    /* now insert earlier one before later one for the inverse reason */
-    addpos234(tree, p2, index1);
-    addpos234(tree, p1, index2);
-}
-- (void)clear
-{
-    char *p;
-    while ((p = delpos234(tree, 0)) != NULL)
-       sfree(p);
-}
-- (int)numberOfRowsInTableView:(NSTableView *)aTableView
-{
-    return count234(tree);
-}
-- (id)tableView:(NSTableView *)aTableView
-    objectValueForTableColumn:(NSTableColumn *)aTableColumn
-    row:(int)rowIndex
-{
-    int j = [[aTableColumn identifier] intValue];
-    char *p = index234(tree, rowIndex);
-
-    while (j >= 0) {
-       p += strcspn(p, "\t");
-       if (*p) p++;
-       j--;
-    }
-
-    return [NSString stringWithCString:p length:strcspn(p, "\t")];
-}
-@end
-
-/*
- * Object to receive messages from various control classes.
- */
-@class Receiver;
-
-struct fe_dlg {
-    NSWindow *window;
-    NSObject *target;
-    SEL action;
-    tree234 *byctrl;
-    tree234 *bywidget;
-    tree234 *boxes;
-    void *data;                               /* passed to portable side */
-    Receiver *rec;
-};
-
-@interface Receiver : NSObject
-{
-    struct fe_dlg *d;
-}
-- (id)initWithStruct:(struct fe_dlg *)aStruct;
-@end
-
-struct fe_ctrl {
-    union control *ctrl;
-    NSButton *button, *button2;
-    NSTextField *label, *editbox;
-    NSComboBox *combobox;
-    NSButton **radiobuttons;
-    NSTextView *textview;
-    NSPopUpButton *popupbutton;
-    NSTableView *tableview;
-    NSScrollView *scrollview;
-    int nradiobuttons;
-};
-
-static int fe_ctrl_cmp_by_ctrl(void *av, void *bv)
-{
-    struct fe_ctrl *a = (struct fe_ctrl *)av;
-    struct fe_ctrl *b = (struct fe_ctrl *)bv;
-
-    if (a->ctrl < b->ctrl)
-       return -1;
-    if (a->ctrl > b->ctrl)
-       return +1;
-    return 0;
-}
-
-static int fe_ctrl_find_by_ctrl(void *av, void *bv)
-{
-    union control *a = (union control *)av;
-    struct fe_ctrl *b = (struct fe_ctrl *)bv;
-
-    if (a < b->ctrl)
-       return -1;
-    if (a > b->ctrl)
-       return +1;
-    return 0;
-}
-
-struct fe_box {
-    struct controlset *s;
-    id box;
-};
-
-static int fe_boxcmp(void *av, void *bv)
-{
-    struct fe_box *a = (struct fe_box *)av;
-    struct fe_box *b = (struct fe_box *)bv;
-
-    if (a->s < b->s)
-       return -1;
-    if (a->s > b->s)
-       return +1;
-    return 0;
-}
-
-static int fe_boxfind(void *av, void *bv)
-{
-    struct controlset *a = (struct controlset *)av;
-    struct fe_box *b = (struct fe_box *)bv;
-
-    if (a < b->s)
-       return -1;
-    if (a > b->s)
-       return +1;
-    return 0;
-}
-
-struct fe_backwards {                 /* map Cocoa widgets back to fe_ctrls */
-    id widget;
-    struct fe_ctrl *c;
-};
-
-static int fe_backwards_cmp_by_widget(void *av, void *bv)
-{
-    struct fe_backwards *a = (struct fe_backwards *)av;
-    struct fe_backwards *b = (struct fe_backwards *)bv;
-
-    if (a->widget < b->widget)
-       return -1;
-    if (a->widget > b->widget)
-       return +1;
-    return 0;
-}
-
-static int fe_backwards_find_by_widget(void *av, void *bv)
-{
-    id a = (id)av;
-    struct fe_backwards *b = (struct fe_backwards *)bv;
-
-    if (a < b->widget)
-       return -1;
-    if (a > b->widget)
-       return +1;
-    return 0;
-}
-
-static struct fe_ctrl *fe_ctrl_new(union control *ctrl)
-{
-    struct fe_ctrl *c;
-
-    c = snew(struct fe_ctrl);
-    c->ctrl = ctrl;
-
-    c->button = c->button2 = nil;
-    c->label = nil;
-    c->editbox = nil;
-    c->combobox = nil;
-    c->textview = nil;
-    c->popupbutton = nil;
-    c->tableview = nil;
-    c->scrollview = nil;
-    c->radiobuttons = NULL;
-    c->nradiobuttons = 0;
-
-    return c;
-}
-
-static void fe_ctrl_free(struct fe_ctrl *c)
-{
-    sfree(c->radiobuttons);
-    sfree(c);
-}
-
-static struct fe_ctrl *fe_ctrl_byctrl(struct fe_dlg *d, union control *ctrl)
-{
-    return find234(d->byctrl, ctrl, fe_ctrl_find_by_ctrl);
-}
-
-static void add_box(struct fe_dlg *d, struct controlset *s, id box)
-{
-    struct fe_box *b = snew(struct fe_box);
-    b->box = box;
-    b->s = s;
-    add234(d->boxes, b);
-}
-
-static id find_box(struct fe_dlg *d, struct controlset *s)
-{
-    struct fe_box *b = find234(d->boxes, s, fe_boxfind);
-    return b ? b->box : NULL;
-}
-
-static void add_widget(struct fe_dlg *d, struct fe_ctrl *c, id widget)
-{
-    struct fe_backwards *b = snew(struct fe_backwards);
-    b->widget = widget;
-    b->c = c;
-    add234(d->bywidget, b);
-}
-
-static struct fe_ctrl *find_widget(struct fe_dlg *d, id widget)
-{
-    struct fe_backwards *b = find234(d->bywidget, widget,
-                                    fe_backwards_find_by_widget);
-    return b ? b->c : NULL;
-}
-
-void *fe_dlg_init(void *data, NSWindow *window, NSObject *target, SEL action)
-{
-    struct fe_dlg *d;
-
-    d = snew(struct fe_dlg);
-    d->window = window;
-    d->target = target;
-    d->action = action;
-    d->byctrl = newtree234(fe_ctrl_cmp_by_ctrl);
-    d->bywidget = newtree234(fe_backwards_cmp_by_widget);
-    d->boxes = newtree234(fe_boxcmp);
-    d->data = data;
-    d->rec = [[Receiver alloc] initWithStruct:d];
-
-    return d;
-}
-
-void fe_dlg_free(void *dv)
-{
-    struct fe_dlg *d = (struct fe_dlg *)dv;
-    struct fe_ctrl *c;
-    struct fe_box *b;
-
-    while ( (c = delpos234(d->byctrl, 0)) != NULL )
-       fe_ctrl_free(c);
-    freetree234(d->byctrl);
-
-    while ( (c = delpos234(d->bywidget, 0)) != NULL )
-       sfree(c);
-    freetree234(d->bywidget);
-
-    while ( (b = delpos234(d->boxes, 0)) != NULL )
-       sfree(b);
-    freetree234(d->boxes);
-
-    [d->rec release];
-
-    sfree(d);
-}
-
-@implementation Receiver
-- (id)initWithStruct:(struct fe_dlg *)aStruct
-{
-    self = [super init];
-    d = aStruct;
-    return self;
-}
-- (void)buttonPushed:(id)sender
-{
-    struct fe_ctrl *c = find_widget(d, sender);
-
-    assert(c && c->ctrl->generic.type == CTRL_BUTTON);
-    c->ctrl->generic.handler(c->ctrl, d, d->data, EVENT_ACTION);
-}
-- (void)checkboxChanged:(id)sender
-{
-    struct fe_ctrl *c = find_widget(d, sender);
-
-    assert(c && c->ctrl->generic.type == CTRL_CHECKBOX);
-    c->ctrl->generic.handler(c->ctrl, d, d->data, EVENT_VALCHANGE);
-}
-- (void)radioChanged:(id)sender
-{
-    struct fe_ctrl *c = find_widget(d, sender);
-    int j;
-
-    assert(c && c->radiobuttons);
-    for (j = 0; j < c->nradiobuttons; j++)
-       if (sender != c->radiobuttons[j])
-           [c->radiobuttons[j] setState:NSOffState];
-    c->ctrl->generic.handler(c->ctrl, d, d->data, EVENT_VALCHANGE);
-}
-- (void)popupMenuSelected:(id)sender
-{
-    struct fe_ctrl *c = find_widget(d, sender);
-    c->ctrl->generic.handler(c->ctrl, d, d->data, EVENT_VALCHANGE);
-}
-- (void)controlTextDidChange:(NSNotification *)notification
-{
-    id widget = [notification object];
-    struct fe_ctrl *c = find_widget(d, widget);
-    assert(c && c->ctrl->generic.type == CTRL_EDITBOX);
-    c->ctrl->generic.handler(c->ctrl, d, d->data, EVENT_VALCHANGE);
-}
-- (void)controlTextDidEndEditing:(NSNotification *)notification
-{
-    id widget = [notification object];
-    struct fe_ctrl *c = find_widget(d, widget);
-    assert(c && c->ctrl->generic.type == CTRL_EDITBOX);
-    c->ctrl->generic.handler(c->ctrl, d, d->data, EVENT_REFRESH);
-}
-- (void)tableViewSelectionDidChange:(NSNotification *)notification
-{
-    id widget = [notification object];
-    struct fe_ctrl *c = find_widget(d, widget);
-    assert(c && c->ctrl->generic.type == CTRL_LISTBOX);
-    c->ctrl->generic.handler(c->ctrl, d, d->data, EVENT_SELCHANGE);
-}
-- (BOOL)tableView:(NSTableView *)aTableView
-    shouldEditTableColumn:(NSTableColumn *)aTableColumn
-    row:(int)rowIndex
-{
-    return NO;                        /* no editing permitted */
-}
-- (void)listDoubleClicked:(id)sender
-{
-    struct fe_ctrl *c = find_widget(d, sender);
-    assert(c && c->ctrl->generic.type == CTRL_LISTBOX);
-    c->ctrl->generic.handler(c->ctrl, d, d->data, EVENT_ACTION);
-}
-- (void)dragListButton:(id)sender
-{
-    struct fe_ctrl *c = find_widget(d, sender);
-    int direction, row, nrows;
-    assert(c && c->ctrl->generic.type == CTRL_LISTBOX &&
-          c->ctrl->listbox.draglist);
-
-    if (sender == c->button)
-       direction = -1;                /* up */
-    else
-       direction = +1;                /* down */
-
-    row = [c->tableview selectedRow];
-    nrows = [c->tableview numberOfRows];
-
-    if (row + direction < 0 || row + direction >= nrows) {
-       NSBeep();
-       return;
-    }
-
-    [[c->tableview dataSource] swap:row with:row+direction];
-    [c->tableview reloadData];
-    [c->tableview selectRow:row+direction byExtendingSelection:NO];
-
-    c->ctrl->generic.handler(c->ctrl, d, d->data, EVENT_VALCHANGE);
-}
-@end
-
-void create_ctrls(void *dv, NSView *parent, struct controlset *s,
-                 int *minw, int *minh)
-{
-    struct fe_dlg *d = (struct fe_dlg *)dv;
-    int ccw[100];                     /* cumulative column widths */
-    int cypos[100];
-    int ncols;
-    int wmin = 0, hmin = 0;
-    int i, j, cw, ch;
-    NSRect rect;
-    NSFont *textviewfont = nil;
-    int boxh = 0, boxw = 0;
-
-    if (!s->boxname && s->boxtitle) {
-        /* This controlset is a panel title. */
-
-       NSTextField *tf;
-
-       tf = [[NSTextField alloc] initWithFrame:NSMakeRect(0,0,1,1)];
-       [tf setEditable:NO];
-       [tf setSelectable:NO];
-       [tf setBordered:NO];
-       [tf setDrawsBackground:NO];
-       [tf setStringValue:[NSString stringWithCString:s->boxtitle]];
-       [tf sizeToFit];
-       rect = [tf frame];
-       [parent addSubview:tf];
-
-       /*
-        * I'm going to store this NSTextField in the boxes tree,
-        * because I really can't face having a special tree234
-        * mapping controlsets to panel titles.
-        */
-       add_box(d, s, tf);
-
-       *minw = rect.size.width;
-       *minh = rect.size.height;
-
-       return;
-    }
-
-    if (*s->boxname) {
-       /*
-        * Create an NSBox to contain this subset of controls.
-        */
-       NSBox *box;
-       NSRect tmprect;
-
-       box = [[NSBox alloc] initWithFrame:NSMakeRect(0,0,1,1)];
-       if (s->boxtitle)
-           [box setTitle:[NSString stringWithCString:s->boxtitle]];
-       else
-           [box setTitlePosition:NSNoTitle];
-       add_box(d, s, box);
-       tmprect = [box frame];
-       [box setContentViewMargins:NSMakeSize(20,20)];
-       [box setFrameFromContentFrame:NSMakeRect(100,100,100,100)];
-       rect = [box frame];
-       [box setFrame:tmprect];
-       boxh = (int)(rect.size.height - 100);
-       boxw = (int)(rect.size.width - 100);
-       [parent addSubview:box];
-
-       if (s->boxtitle)
-           boxh += [[box titleFont] pointSize];
-
-       /*
-        * All subsequent controls will be placed within this box.
-        */
-       parent = box;
-    }
-
-    ncols = 1;
-    ccw[0] = 0;
-    ccw[1] = 100;
-    cypos[0] = 0;
-
-    /*
-     * Now iterate through the controls themselves, create them,
-     * and add their width and height to the overall width/height
-     * calculation.
-     */
-    for (i = 0; i < s->ncontrols; i++) {
-       union control *ctrl = s->ctrls[i];
-       struct fe_ctrl *c;
-       int colstart = COLUMN_START(ctrl->generic.column);
-       int colspan = COLUMN_SPAN(ctrl->generic.column);
-       int colend = colstart + colspan;
-       int ytop, wthis;
-
-        switch (ctrl->generic.type) {
-          case CTRL_COLUMNS:
-           for (j = 1; j < ncols; j++)
-               if (cypos[0] < cypos[j])
-                   cypos[0] = cypos[j];
-
-           assert(ctrl->columns.ncols < lenof(ccw));
-
-           ccw[0] = 0;
-           for (j = 0; j < ctrl->columns.ncols; j++) {
-               ccw[j+1] = ccw[j] + (ctrl->columns.percentages ?
-                                    ctrl->columns.percentages[j] : 100);
-               cypos[j] = cypos[0];
-           }
-
-           ncols = ctrl->columns.ncols;
-
-            continue;                  /* no actual control created */
-          case CTRL_TABDELAY:
-           /*
-            * I'm currently uncertain that we can implement tab
-            * order in OS X.
-            */
-            continue;                  /* no actual control created */
-       }
-
-       c = fe_ctrl_new(ctrl);
-       add234(d->byctrl, c);
-
-       cw = ch = 0;
-
-        switch (ctrl->generic.type) {
-          case CTRL_BUTTON:
-          case CTRL_CHECKBOX:
-           {
-               NSButton *b;
-
-               b = [[MyButton alloc] initWithFrame:NSMakeRect(0, 0, 1, 1)];
-               [b setBezelStyle:NSRoundedBezelStyle];
-               if (ctrl->generic.type == CTRL_CHECKBOX)
-                   [b setButtonType:NSSwitchButton];
-               [b setTitle:[NSString stringWithCString:ctrl->generic.label]];
-               if (ctrl->button.isdefault)
-                   [b setKeyEquivalent:@"\r"];
-               else if (ctrl->button.iscancel)
-                   [b setKeyEquivalent:@"\033"];
-               [b sizeToFit];
-               rect = [b frame];
-
-               [parent addSubview:b];
-
-               [b setTarget:d->rec];
-               if (ctrl->generic.type == CTRL_CHECKBOX)
-                   [b setAction:@selector(checkboxChanged:)];
-               else
-                   [b setAction:@selector(buttonPushed:)];
-               add_widget(d, c, b);
-
-               c->button = b;
-
-               cw = rect.size.width;
-               ch = rect.size.height;
-           }
-           break;
-         case CTRL_EDITBOX:
-           {
-               int editp = ctrl->editbox.percentwidth;
-               int labelp = editp == 100 ? 100 : 100 - editp;
-               NSTextField *tf;
-               NSComboBox *cb;
-
-               tf = [[NSTextField alloc] initWithFrame:NSMakeRect(0,0,1,1)];
-               [tf setEditable:NO];
-               [tf setSelectable:NO];
-               [tf setBordered:NO];
-               [tf setDrawsBackground:NO];
-               [tf setStringValue:[NSString
-                                   stringWithCString:ctrl->generic.label]];
-               [tf sizeToFit];
-               rect = [tf frame];
-               [parent addSubview:tf];
-               c->label = tf;
-
-               cw = rect.size.width * 100 / labelp;
-               ch = rect.size.height;
-
-               if (ctrl->editbox.has_list) {
-                   cb = [[NSComboBox alloc]
-                         initWithFrame:NSMakeRect(0,0,1,1)];
-                   [cb setStringValue:@"x"];
-                   [cb sizeToFit];
-                   rect = [cb frame];
-                   [parent addSubview:cb];
-                   c->combobox = cb;
-               } else {
-                   if (ctrl->editbox.password)
-                       tf = [NSSecureTextField alloc];
-                   else
-                       tf = [NSTextField alloc];
-
-                   tf = [tf initWithFrame:NSMakeRect(0,0,1,1)];
-                   [tf setEditable:YES];
-                   [tf setSelectable:YES];
-                   [tf setBordered:YES];
-                   [tf setStringValue:@"x"];
-                   [tf sizeToFit];
-                   rect = [tf frame];
-                   [parent addSubview:tf];
-                   c->editbox = tf;
-
-                   [tf setDelegate:d->rec];
-                   add_widget(d, c, tf);
-               }
-
-               if (editp == 100) {
-                   /* the edit box and its label are vertically separated */
-                   ch += VSPACING + rect.size.height;
-               } else {
-                   /* the edit box and its label are horizontally separated */
-                   if (ch < rect.size.height)
-                       ch = rect.size.height;
-               }
-
-               if (cw < rect.size.width * 100 / editp)
-                   cw = rect.size.width * 100 / editp;
-           }
-           break;
-         case CTRL_TEXT:
-           {
-               NSTextView *tv;
-               int testwid;
-
-               if (!textviewfont) {
-                   NSTextField *tf;
-                   tf = [[NSTextField alloc] init];
-                   textviewfont = [tf font];
-                   [tf release];
-               }
-
-               testwid = (ccw[colend] - ccw[colstart]) * 3;
-
-               tv = [[NSTextView alloc]
-                     initWithFrame:NSMakeRect(0,0,testwid,1)];
-               [tv setEditable:NO];
-               [tv setSelectable:NO];
-               //[tv setBordered:NO];
-               [tv setDrawsBackground:NO];
-               [tv setFont:textviewfont];
-               [tv setString:
-                [NSString stringWithCString:ctrl->generic.label]];
-               rect = [tv frame];
-               [tv sizeToFit];
-               [parent addSubview:tv];
-               c->textview = tv;
-
-               cw = rect.size.width;
-               ch = rect.size.height;
-           }
-           break;
-         case CTRL_RADIO:
-           {
-               NSTextField *tf;
-               int j;
-
-               if (ctrl->generic.label) {
-                   tf = [[NSTextField alloc]
-                         initWithFrame:NSMakeRect(0,0,1,1)];
-                   [tf setEditable:NO];
-                   [tf setSelectable:NO];
-                   [tf setBordered:NO];
-                   [tf setDrawsBackground:NO];
-                   [tf setStringValue:
-                    [NSString stringWithCString:ctrl->generic.label]];
-                   [tf sizeToFit];
-                   rect = [tf frame];
-                   [parent addSubview:tf];
-                   c->label = tf;
-
-                   cw = rect.size.width;
-                   ch = rect.size.height;
-               } else {
-                   cw = 0;
-                   ch = -VSPACING;    /* compensate for next advance */
-               }
-
-               c->nradiobuttons = ctrl->radio.nbuttons;
-               c->radiobuttons = snewn(ctrl->radio.nbuttons, NSButton *);
-
-               for (j = 0; j < ctrl->radio.nbuttons; j++) {
-                   NSButton *b;
-                   int ncols;
-
-                   b = [[MyButton alloc] initWithFrame:NSMakeRect(0,0,1,1)];
-                   [b setBezelStyle:NSRoundedBezelStyle];
-                   [b setButtonType:NSRadioButton];
-                   [b setTitle:[NSString
-                                stringWithCString:ctrl->radio.buttons[j]]];
-                   [b sizeToFit];
-                   rect = [b frame];
-                   [parent addSubview:b];
-
-                   c->radiobuttons[j] = b;
-
-                   [b setTarget:d->rec];
-                   [b setAction:@selector(radioChanged:)];
-                   add_widget(d, c, b);
-
-                   /*
-                    * Add to the height every time we place a
-                    * button in column 0.
-                    */
-                   if (j % ctrl->radio.ncolumns == 0) {
-                       ch += rect.size.height + VSPACING;
-                   }
-
-                   /*
-                    * Add to the width by working out how many
-                    * columns this button spans.
-                    */
-                   if (j == ctrl->radio.nbuttons - 1)
-                       ncols = (ctrl->radio.ncolumns -
-                                (j % ctrl->radio.ncolumns));
-                   else
-                       ncols = 1;
-
-                   if (cw < rect.size.width * ctrl->radio.ncolumns / ncols)
-                       cw = rect.size.width * ctrl->radio.ncolumns / ncols;
-               }
-           }
-           break;
-         case CTRL_FILESELECT:
-         case CTRL_FONTSELECT:
-           {
-               NSTextField *tf;
-               NSButton *b;
-               int kh;
-
-               tf = [[NSTextField alloc] initWithFrame:NSMakeRect(0,0,1,1)];
-               [tf setEditable:NO];
-               [tf setSelectable:NO];
-               [tf setBordered:NO];
-               [tf setDrawsBackground:NO];
-               [tf setStringValue:[NSString
-                                   stringWithCString:ctrl->generic.label]];
-               [tf sizeToFit];
-               rect = [tf frame];
-               [parent addSubview:tf];
-               c->label = tf;
-
-               cw = rect.size.width;
-               ch = rect.size.height;
-
-               tf = [NSTextField alloc];
-               tf = [tf initWithFrame:NSMakeRect(0,0,1,1)];
-               if (ctrl->generic.type == CTRL_FILESELECT) {
-                   [tf setEditable:YES];
-                   [tf setSelectable:YES];
-                   [tf setBordered:YES];
-               } else {
-                   [tf setEditable:NO];
-                   [tf setSelectable:NO];
-                   [tf setBordered:NO];
-                   [tf setDrawsBackground:NO];
-               }
-               [tf setStringValue:@"x"];
-               [tf sizeToFit];
-               rect = [tf frame];
-               [parent addSubview:tf];
-               c->editbox = tf;
-
-               kh = rect.size.height;
-               if (cw < rect.size.width * 4 / 3)
-                   cw = rect.size.width * 4 / 3;
-
-               b = [[MyButton alloc] initWithFrame:NSMakeRect(0, 0, 1, 1)];
-               [b setBezelStyle:NSRoundedBezelStyle];
-               if (ctrl->generic.type == CTRL_FILESELECT)
-                   [b setTitle:@"Browse..."];
-               else
-                   [b setTitle:@"Change..."];
-               // [b setKeyEquivalent:somethingorother];
-               // [b setTarget:somethingorother];
-               // [b setAction:somethingorother];
-               [b sizeToFit];
-               rect = [b frame];
-               [parent addSubview:b];
-
-               c->button = b;
-
-               if (kh < rect.size.height)
-                   kh = rect.size.height;
-               ch += VSPACING + kh;
-               if (cw < rect.size.width * 4)
-                   cw = rect.size.width * 4;
-           }
-           break;
-         case CTRL_LISTBOX:
-           {
-               int listp = ctrl->listbox.percentwidth;
-               int labelp = listp == 100 ? 100 : 100 - listp;
-               NSTextField *tf;
-               NSPopUpButton *pb;
-               NSTableView *tv;
-               NSScrollView *sv;
-
-               if (ctrl->generic.label) {
-                   tf = [[NSTextField alloc]
-                         initWithFrame:NSMakeRect(0,0,1,1)];
-                   [tf setEditable:NO];
-                   [tf setSelectable:NO];
-                   [tf setBordered:NO];
-                   [tf setDrawsBackground:NO];
-                   [tf setStringValue:
-                    [NSString stringWithCString:ctrl->generic.label]];
-                   [tf sizeToFit];
-                   rect = [tf frame];
-                   [parent addSubview:tf];
-                   c->label = tf;
-
-                   cw = rect.size.width;
-                   ch = rect.size.height;
-               } else {
-                   cw = 0;
-                   ch = -VSPACING;    /* compensate for next advance */
-               }
-
-               if (ctrl->listbox.height == 0) {
-                   pb = [[NSPopUpButton alloc]
-                         initWithFrame:NSMakeRect(0,0,1,1)];
-                   [pb sizeToFit];
-                   rect = [pb frame];
-                   [parent addSubview:pb];
-                   c->popupbutton = pb;
-
-                   [pb setTarget:d->rec];
-                   [pb setAction:@selector(popupMenuSelected:)];
-                   add_widget(d, c, pb);
-               } else {
-                   assert(listp == 100);
-                   if (ctrl->listbox.draglist) {
-                       int bi;
-
-                       listp = 75;
-
-                       for (bi = 0; bi < 2; bi++) {
-                           NSButton *b;
-                           b = [[MyButton alloc]
-                                initWithFrame:NSMakeRect(0, 0, 1, 1)];
-                           [b setBezelStyle:NSRoundedBezelStyle];
-                           if (bi == 0)
-                               [b setTitle:@"Up"];
-                           else
-                               [b setTitle:@"Down"];
-                           [b sizeToFit];
-                           rect = [b frame];
-                           [parent addSubview:b];
-
-                           if (bi == 0)
-                               c->button = b;
-                           else
-                               c->button2 = b;
-
-                           [b setTarget:d->rec];
-                           [b setAction:@selector(dragListButton:)];
-                           add_widget(d, c, b);
-
-                           if (cw < rect.size.width * 4)
-                               cw = rect.size.width * 4;
-                       }
-                   }
-
-                   sv = [[NSScrollView alloc] initWithFrame:
-                         NSMakeRect(20,20,10,10)];
-                   [sv setBorderType:NSLineBorder];
-                   tv = [[NSTableView alloc] initWithFrame:[sv frame]];
-                   [[tv headerView] setFrame:NSMakeRect(0,0,0,0)];
-                   [sv setDocumentView:tv];
-                   [parent addSubview:sv];
-                   [sv setHasVerticalScroller:YES];
-                   [sv setAutohidesScrollers:YES];
-                   [tv setAllowsColumnReordering:NO];
-                   [tv setAllowsColumnResizing:NO];
-                   [tv setAllowsMultipleSelection:ctrl->listbox.multisel];
-                   [tv setAllowsEmptySelection:YES];
-                   [tv setAllowsColumnSelection:YES];
-                   [tv setDataSource:[[MyTableSource alloc] init]];
-                   rect = [tv frame];
-                   /*
-                    * For some reason this consistently comes out
-                    * one short. Add one.
-                    */
-                   rect.size.height = (ctrl->listbox.height+1)*[tv rowHeight];
-                   [sv setFrame:rect];
-                   c->tableview = tv;
-                   c->scrollview = sv;
-
-                   [tv setDelegate:d->rec];
-                   [tv setTarget:d->rec];
-                   [tv setDoubleAction:@selector(listDoubleClicked:)];
-                   add_widget(d, c, tv);
-               }
-
-               if (c->tableview) {
-                   int ncols, *percentages;
-                   int hundred = 100;
-
-                   if (ctrl->listbox.ncols) {
-                       ncols = ctrl->listbox.ncols;
-                       percentages = ctrl->listbox.percentages;
-                   } else {
-                       ncols = 1;
-                       percentages = &hundred;
-                   }
-
-                   for (j = 0; j < ncols; j++) {
-                       NSTableColumn *col;
-
-                       col = [[NSTableColumn alloc] initWithIdentifier:
-                              [NSNumber numberWithInt:j]];
-                       [c->tableview addTableColumn:col];
-                   }
-               }
-
-               if (labelp == 100) {
-                   /* the list and its label are vertically separated */
-                   ch += VSPACING + rect.size.height;
-               } else {
-                   /* the list and its label are horizontally separated */
-                   if (ch < rect.size.height)
-                       ch = rect.size.height;
-               }
-
-               if (cw < rect.size.width * 100 / listp)
-                   cw = rect.size.width * 100 / listp;
-           }
-           break;
-       }
-
-       /*
-        * Update the width and height data for the control we've
-        * just created.
-        */
-       ytop = 0;
-
-       for (j = colstart; j < colend; j++) {
-           if (ytop < cypos[j])
-               ytop = cypos[j];
-       }
-
-       for (j = colstart; j < colend; j++)
-           cypos[j] = ytop + ch + VSPACING;
-
-       if (hmin < ytop + ch)
-           hmin = ytop + ch;
-
-       wthis = (cw + HSPACING) * 100 / (ccw[colend] - ccw[colstart]);
-       wthis -= HSPACING;
-
-       if (wmin < wthis)
-           wmin = wthis;
-    }
-
-    if (*s->boxname) {
-       /*
-        * Add a bit to the width and height for the box.
-        */
-       wmin += boxw;
-       hmin += boxh;
-    }
-
-    //printf("For controlset %s/%s, returning w=%d h=%d\n",
-    //       s->pathname, s->boxname, wmin, hmin);
-    *minw = wmin;
-    *minh = hmin;
-}
-
-int place_ctrls(void *dv, struct controlset *s, int leftx, int topy,
-               int width)
-{
-    struct fe_dlg *d = (struct fe_dlg *)dv;
-    int ccw[100];                     /* cumulative column widths */
-    int cypos[100];
-    int ncols;
-    int i, j, ret;
-    int boxh = 0, boxw = 0;
-
-    if (!s->boxname && s->boxtitle) {
-        /* Size and place the panel title. */
-
-       NSTextField *tf = find_box(d, s);
-       NSRect rect;
-
-       rect = [tf frame];
-       [tf setFrame:NSMakeRect(leftx, topy-rect.size.height,
-                               width, rect.size.height)];
-       return rect.size.height;
-    }
-
-    if (*s->boxname) {
-       NSRect rect, tmprect;
-       NSBox *box = find_box(d, s);
-
-       assert(box != NULL);
-       tmprect = [box frame];
-       [box setFrameFromContentFrame:NSMakeRect(100,100,100,100)];
-       rect = [box frame];
-       [box setFrame:tmprect];
-       boxw = rect.size.width - 100;
-       boxh = rect.size.height - 100;
-       if (s->boxtitle)
-           boxh += [[box titleFont] pointSize];
-       topy -= boxh;
-       width -= boxw;
-    }
-
-    ncols = 1;
-    ccw[0] = 0;
-    ccw[1] = 100;
-    cypos[0] = topy;
-    ret = 0;
-
-    /*
-     * Now iterate through the controls themselves, placing them
-     * appropriately.
-     */
-    for (i = 0; i < s->ncontrols; i++) {
-       union control *ctrl = s->ctrls[i];
-       struct fe_ctrl *c;
-       int colstart = COLUMN_START(ctrl->generic.column);
-       int colspan = COLUMN_SPAN(ctrl->generic.column);
-       int colend = colstart + colspan;
-       int xthis, ythis, wthis, ch;
-       NSRect rect;
-
-        switch (ctrl->generic.type) {
-          case CTRL_COLUMNS:
-           for (j = 1; j < ncols; j++)
-               if (cypos[0] > cypos[j])
-                   cypos[0] = cypos[j];
-
-           assert(ctrl->columns.ncols < lenof(ccw));
-
-           ccw[0] = 0;
-           for (j = 0; j < ctrl->columns.ncols; j++) {
-               ccw[j+1] = ccw[j] + (ctrl->columns.percentages ?
-                                    ctrl->columns.percentages[j] : 100);
-               cypos[j] = cypos[0];
-           }
-
-           ncols = ctrl->columns.ncols;
-
-            continue;                  /* no actual control created */
-          case CTRL_TABDELAY:
-            continue;                  /* nothing to do here, move along */
-       }
-
-       c = fe_ctrl_byctrl(d, ctrl);
-
-       ch = 0;
-       ythis = topy;
-
-       for (j = colstart; j < colend; j++) {
-           if (ythis > cypos[j])
-               ythis = cypos[j];
-       }
-
-       xthis = (width + HSPACING) * ccw[colstart] / 100;
-       wthis = (width + HSPACING) * ccw[colend] / 100 - HSPACING - xthis;
-       xthis += leftx;
-
-        switch (ctrl->generic.type) {
-          case CTRL_BUTTON:
-         case CTRL_CHECKBOX:
-           rect = [c->button frame];
-           [c->button setFrame:NSMakeRect(xthis,ythis-rect.size.height,wthis,
-                                          rect.size.height)];
-           ch = rect.size.height;
-           break;
-         case CTRL_EDITBOX:
-           {
-               int editp = ctrl->editbox.percentwidth;
-               int labelp = editp == 100 ? 100 : 100 - editp;
-               int lheight, theight, rheight, ynext, editw;
-               NSControl *edit = (c->editbox ? c->editbox : c->combobox);
-
-               rect = [c->label frame];
-               lheight = rect.size.height;
-               rect = [edit frame];
-               theight = rect.size.height;
-
-               if (editp == 100)
-                   rheight = lheight;
-               else
-                   rheight = (lheight < theight ? theight : lheight);
-
-               [c->label setFrame:
-                NSMakeRect(xthis, ythis-(rheight+lheight)/2,
-                           (wthis + HSPACING) * labelp / 100 - HSPACING,
-                           lheight)];
-               if (editp == 100) {
-                   ynext = ythis - rheight - VSPACING;
-                   rheight = theight;
-               } else {
-                   ynext = ythis;
-               }
-
-               editw = (wthis + HSPACING) * editp / 100 - HSPACING;
-
-               [edit setFrame:
-                NSMakeRect(xthis+wthis-editw, ynext-(rheight+theight)/2,
-                           editw, theight)];
-
-               ch = (ythis - ynext) + theight;
-           }
-           break;
-          case CTRL_TEXT:
-           [c->textview setFrame:NSMakeRect(xthis, 0, wthis, 1)];
-           [c->textview sizeToFit];
-           rect = [c->textview frame];
-           [c->textview setFrame:NSMakeRect(xthis, ythis-rect.size.height,
-                                            wthis, rect.size.height)];
-           ch = rect.size.height;
-           break;
-         case CTRL_RADIO:
-           {
-               int j, ynext;
-
-               if (c->label) {
-                   rect = [c->label frame];
-                   [c->label setFrame:NSMakeRect(xthis,ythis-rect.size.height,
-                                                 wthis,rect.size.height)];
-                   ynext = ythis - rect.size.height - VSPACING;
-               } else
-                   ynext = ythis;
-
-               for (j = 0; j < ctrl->radio.nbuttons; j++) {
-                   int col = j % ctrl->radio.ncolumns;
-                   int ncols;
-                   int lx,rx;
-
-                   if (j == ctrl->radio.nbuttons - 1)
-                       ncols = ctrl->radio.ncolumns - col;
-                   else
-                       ncols = 1;
-
-                   lx = (wthis + HSPACING) * col / ctrl->radio.ncolumns;
-                   rx = ((wthis + HSPACING) *
-                         (col+ncols) / ctrl->radio.ncolumns) - HSPACING;
-
-                   /*
-                    * Set the frame size.
-                    */
-                   rect = [c->radiobuttons[j] frame];
-                   [c->radiobuttons[j] setFrame:
-                    NSMakeRect(lx+xthis, ynext-rect.size.height,
-                               rx-lx, rect.size.height)];
-
-                   /*
-                    * Advance to next line if we're in the last
-                    * column.
-                    */
-                   if (col + ncols == ctrl->radio.ncolumns)
-                       ynext -= rect.size.height + VSPACING;
-               }
-               ch = (ythis - ynext) - VSPACING;
-           }
-           break;
-         case CTRL_FILESELECT:
-         case CTRL_FONTSELECT:
-           {
-               int ynext, eh, bh, th, mx;
-
-               rect = [c->label frame];
-               [c->label setFrame:NSMakeRect(xthis,ythis-rect.size.height,
-                                             wthis,rect.size.height)];
-               ynext = ythis - rect.size.height - VSPACING;
-
-               rect = [c->editbox frame];
-               eh = rect.size.height;
-               rect = [c->button frame];
-               bh = rect.size.height;
-               th = (eh > bh ? eh : bh);
-
-               mx = (wthis + HSPACING) * 3 / 4 - HSPACING;
-
-               [c->editbox setFrame:
-                NSMakeRect(xthis, ynext-(th+eh)/2, mx, eh)];
-               [c->button setFrame:
-                NSMakeRect(xthis+mx+HSPACING, ynext-(th+bh)/2,
-                           wthis-mx-HSPACING, bh)];
-
-               ch = (ythis - ynext) + th + VSPACING;
-           }
-           break;
-         case CTRL_LISTBOX:
-           {
-               int listp = ctrl->listbox.percentwidth;
-               int labelp = listp == 100 ? 100 : 100 - listp;
-               int lheight, theight, rheight, ynext, listw, xlist;
-               NSControl *list = (c->scrollview ? (id)c->scrollview :
-                                  (id)c->popupbutton);
-
-               if (ctrl->listbox.draglist) {
-                   assert(listp == 100);
-                   listp = 75;
-               }
-
-               rect = [list frame];
-               theight = rect.size.height;
-
-               if (c->label) {
-                   rect = [c->label frame];
-                   lheight = rect.size.height;
-
-                   if (labelp == 100)
-                       rheight = lheight;
-                   else
-                       rheight = (lheight < theight ? theight : lheight);
-
-                   [c->label setFrame:
-                    NSMakeRect(xthis, ythis-(rheight+lheight)/2,
-                               (wthis + HSPACING) * labelp / 100 - HSPACING,
-                               lheight)];
-                   if (labelp == 100) {
-                       ynext = ythis - rheight - VSPACING;
-                       rheight = theight;
-                   } else {
-                       ynext = ythis;
-                   }
-               } else {
-                   ynext = ythis;
-                   rheight = theight;
-               }
-
-               listw = (wthis + HSPACING) * listp / 100 - HSPACING;
-
-               if (labelp == 100)
-                   xlist = xthis;
-               else
-                   xlist = xthis+wthis-listw;
-
-               [list setFrame: NSMakeRect(xlist, ynext-(rheight+theight)/2,
-                                          listw, theight)];
-
-               /*
-                * Size the columns for the table view.
-                */
-               if (c->tableview) {
-                   int ncols, *percentages;
-                   int hundred = 100;
-                   int cpercent = 0, cpixels = 0;
-                   NSArray *cols;
-
-                   if (ctrl->listbox.ncols) {
-                       ncols = ctrl->listbox.ncols;
-                       percentages = ctrl->listbox.percentages;
-                   } else {
-                       ncols = 1;
-                       percentages = &hundred;
-                   }
-
-                   cols = [c->tableview tableColumns];
-
-                   for (j = 0; j < ncols; j++) {
-                       NSTableColumn *col = [cols objectAtIndex:j];
-                       int newcpixels;
-
-                       cpercent += percentages[j];
-                       newcpixels = listw * cpercent / 100;
-                       [col setWidth:newcpixels-cpixels];
-                       cpixels = newcpixels;
-                   }
-               }
-
-               ch = (ythis - ynext) + theight;
-
-               if (c->button) {
-                   int b2height, centre;
-                   int bx, bw;
-
-                   /*
-                    * Place the Up and Down buttons for a drag list.
-                    */
-                   assert(c->button2);
-
-                   rect = [c->button frame];
-                   b2height = VSPACING + 2 * rect.size.height;
-
-                   centre = ynext - rheight/2;
-
-                   bx = (wthis + HSPACING) * 3 / 4;
-                   bw = wthis - bx;
-                   bx += leftx;
-
-                   [c->button setFrame:
-                    NSMakeRect(bx, centre+b2height/2-rect.size.height,
-                               bw, rect.size.height)];
-                   [c->button2 setFrame:
-                    NSMakeRect(bx, centre-b2height/2,
-                               bw, rect.size.height)];
-               }
-           }
-           break;
-       }
-
-       for (j = colstart; j < colend; j++)
-           cypos[j] = ythis - ch - VSPACING;
-       if (ret < topy - (ythis - ch))
-           ret = topy - (ythis - ch);
-    }
-
-    if (*s->boxname) {
-       NSBox *box = find_box(d, s);
-       assert(box != NULL);
-       [box sizeToFit];
-
-       if (s->boxtitle) {
-           NSRect rect = [box frame];
-           rect.size.height += [[box titleFont] pointSize];
-           [box setFrame:rect];
-       }
-
-       ret += boxh;
-    }
-
-    //printf("For controlset %s/%s, returning ret=%d\n",
-    //       s->pathname, s->boxname, ret);
-    return ret;
-}
-
-void select_panel(void *dv, struct controlbox *b, const char *name)
-{
-    struct fe_dlg *d = (struct fe_dlg *)dv;
-    int i, j, hidden;
-    struct controlset *s;
-    union control *ctrl;
-    struct fe_ctrl *c;
-    NSBox *box;
-
-    for (i = 0; i < b->nctrlsets; i++) {
-       s = b->ctrlsets[i];
-
-       if (*s->pathname) {
-           hidden = !strcmp(s->pathname, name) ? NO : YES;
-
-           if ((box = find_box(d, s)) != NULL) {
-               [box setHidden:hidden];
-           } else {
-               for (j = 0; j < s->ncontrols; j++) {
-                   ctrl = s->ctrls[j];
-                   c = fe_ctrl_byctrl(d, ctrl);
-
-                   if (!c)
-                       continue;
-
-                   if (c->label)
-                       [c->label setHidden:hidden];
-                   if (c->button)
-                       [c->button setHidden:hidden];
-                   if (c->button2)
-                       [c->button2 setHidden:hidden];
-                   if (c->editbox)
-                       [c->editbox setHidden:hidden];
-                   if (c->combobox)
-                       [c->combobox setHidden:hidden];
-                   if (c->textview)
-                       [c->textview setHidden:hidden];
-                   if (c->tableview)
-                       [c->tableview setHidden:hidden];
-                   if (c->scrollview)
-                       [c->scrollview setHidden:hidden];
-                   if (c->popupbutton)
-                       [c->popupbutton setHidden:hidden];
-                   if (c->radiobuttons) {
-                       int j;
-                       for (j = 0; j < c->nradiobuttons; j++)
-                           [c->radiobuttons[j] setHidden:hidden];
-                   }
-                   break;
-               }
-           }
-       }
-    }
-}
-
-void dlg_radiobutton_set(union control *ctrl, void *dv, int whichbutton)
-{
-    struct fe_dlg *d = (struct fe_dlg *)dv;
-    struct fe_ctrl *c = fe_ctrl_byctrl(d, ctrl);
-    int j;
-
-    assert(c->radiobuttons);
-    for (j = 0; j < c->nradiobuttons; j++)
-       [c->radiobuttons[j] setState:
-        (j == whichbutton ? NSOnState : NSOffState)];
-}
-
-int dlg_radiobutton_get(union control *ctrl, void *dv)
-{
-    struct fe_dlg *d = (struct fe_dlg *)dv;
-    struct fe_ctrl *c = fe_ctrl_byctrl(d, ctrl);
-    int j;
-
-    assert(c->radiobuttons);
-    for (j = 0; j < c->nradiobuttons; j++)
-       if ([c->radiobuttons[j] state] == NSOnState)
-           return j;
-
-    return 0;                         /* should never reach here */
-}
-
-void dlg_checkbox_set(union control *ctrl, void *dv, int checked)
-{
-    struct fe_dlg *d = (struct fe_dlg *)dv;
-    struct fe_ctrl *c = fe_ctrl_byctrl(d, ctrl);
-
-    assert(c->button);
-    [c->button setState:(checked ? NSOnState : NSOffState)];
-}
-
-int dlg_checkbox_get(union control *ctrl, void *dv)
-{
-    struct fe_dlg *d = (struct fe_dlg *)dv;
-    struct fe_ctrl *c = fe_ctrl_byctrl(d, ctrl);
-
-    assert(c->button);
-    return ([c->button state] == NSOnState);
-}
-
-void dlg_editbox_set(union control *ctrl, void *dv, char const *text)
-{
-    struct fe_dlg *d = (struct fe_dlg *)dv;
-    struct fe_ctrl *c = fe_ctrl_byctrl(d, ctrl);
-
-    if (c->editbox) {
-       [c->editbox setStringValue:[NSString stringWithCString:text]];
-    } else {
-       assert(c->combobox);
-       [c->combobox setStringValue:[NSString stringWithCString:text]];
-    }
-}
-
-void dlg_editbox_get(union control *ctrl, void *dv, char *buffer, int length)
-{
-    struct fe_dlg *d = (struct fe_dlg *)dv;
-    struct fe_ctrl *c = fe_ctrl_byctrl(d, ctrl);
-    NSString *str;
-
-    if (c->editbox) {
-       str = [c->editbox stringValue];
-    } else {
-       assert(c->combobox);
-       str = [c->combobox stringValue];
-    }
-    if (!str)
-       str = @"";
-
-    /* The length parameter to this method doesn't include a trailing NUL */
-    [str getCString:buffer maxLength:length-1];
-}
-
-void dlg_listbox_clear(union control *ctrl, void *dv)
-{
-    struct fe_dlg *d = (struct fe_dlg *)dv;
-    struct fe_ctrl *c = fe_ctrl_byctrl(d, ctrl);
-
-    if (c->tableview) {
-       [[c->tableview dataSource] clear];
-       [c->tableview reloadData];
-    } else {
-       [c->popupbutton removeAllItems];
-    }
-}
-
-void dlg_listbox_del(union control *ctrl, void *dv, int index)
-{
-    struct fe_dlg *d = (struct fe_dlg *)dv;
-    struct fe_ctrl *c = fe_ctrl_byctrl(d, ctrl);
-
-    if (c->tableview) {
-       [[c->tableview dataSource] removestr:index];
-       [c->tableview reloadData];
-    } else {
-       [c->popupbutton removeItemAtIndex:index];
-    }
-}
-
-void dlg_listbox_addwithid(union control *ctrl, void *dv,
-                          char const *text, int id)
-{
-    struct fe_dlg *d = (struct fe_dlg *)dv;
-    struct fe_ctrl *c = fe_ctrl_byctrl(d, ctrl);
-
-    if (c->tableview) {
-       [[c->tableview dataSource] add:text withId:id];
-       [c->tableview reloadData];
-    } else {
-       [c->popupbutton addItemWithTitle:[NSString stringWithCString:text]];
-       [[c->popupbutton lastItem] setTag:id];
-    }
-}
-
-void dlg_listbox_add(union control *ctrl, void *dv, char const *text)
-{
-    dlg_listbox_addwithid(ctrl, dv, text, -1);
-}
-
-int dlg_listbox_getid(union control *ctrl, void *dv, int index)
-{
-    struct fe_dlg *d = (struct fe_dlg *)dv;
-    struct fe_ctrl *c = fe_ctrl_byctrl(d, ctrl);
-
-    if (c->tableview) {
-       return [[c->tableview dataSource] getid:index];
-    } else {
-       return [[c->popupbutton itemAtIndex:index] tag];
-    }
-}
-
-int dlg_listbox_index(union control *ctrl, void *dv)
-{
-    struct fe_dlg *d = (struct fe_dlg *)dv;
-    struct fe_ctrl *c = fe_ctrl_byctrl(d, ctrl);
-
-    if (c->tableview) {
-       return [c->tableview selectedRow];
-    } else {
-       return [c->popupbutton indexOfSelectedItem];
-    }
-}
-
-int dlg_listbox_issel(union control *ctrl, void *dv, int index)
-{
-    struct fe_dlg *d = (struct fe_dlg *)dv;
-    struct fe_ctrl *c = fe_ctrl_byctrl(d, ctrl);
-
-    if (c->tableview) {
-       return [c->tableview isRowSelected:index];
-    } else {
-       return [c->popupbutton indexOfSelectedItem] == index;
-    }
-}
-
-void dlg_listbox_select(union control *ctrl, void *dv, int index)
-{
-    struct fe_dlg *d = (struct fe_dlg *)dv;
-    struct fe_ctrl *c = fe_ctrl_byctrl(d, ctrl);
-
-    if (c->tableview) {
-       [c->tableview selectRow:index byExtendingSelection:NO];
-    } else {
-       [c->popupbutton selectItemAtIndex:index];
-    }
-}
-
-void dlg_text_set(union control *ctrl, void *dv, char const *text)
-{
-    struct fe_dlg *d = (struct fe_dlg *)dv;
-    struct fe_ctrl *c = fe_ctrl_byctrl(d, ctrl);
-
-    assert(c->textview);
-    [c->textview setString:[NSString stringWithCString:text]];
-}
-
-void dlg_label_change(union control *ctrl, void *dlg, char const *text)
-{
-    /*
-     * This function is currently only used by the config box to
-     * switch the labels on the host and port boxes between serial
-     * and network modes. Since OS X does not (yet?) have a serial
-     * back end, this function can safely do nothing for the
-     * moment.
-     */
-}
-
-void dlg_filesel_set(union control *ctrl, void *dv, Filename fn)
-{
-    /* FIXME */
-}
-
-void dlg_filesel_get(union control *ctrl, void *dv, Filename *fn)
-{
-    /* FIXME */
-}
-
-void dlg_fontsel_set(union control *ctrl, void *dv, FontSpec fn)
-{
-    /* FIXME */
-}
-
-void dlg_fontsel_get(union control *ctrl, void *dv, FontSpec *fn)
-{
-    /* FIXME */
-}
-
-void dlg_update_start(union control *ctrl, void *dv)
-{
-    /* FIXME */
-}
-
-void dlg_update_done(union control *ctrl, void *dv)
-{
-    /* FIXME */
-}
-
-void dlg_set_focus(union control *ctrl, void *dv)
-{
-    /* FIXME */
-}
-
-union control *dlg_last_focused(union control *ctrl, void *dv)
-{
-    return NULL; /* FIXME */
-}
-
-void dlg_beep(void *dv)
-{
-    NSBeep();
-}
-
-void dlg_error_msg(void *dv, const char *msg)
-{
-    /* FIXME */
-}
-
-void dlg_end(void *dv, int value)
-{
-    struct fe_dlg *d = (struct fe_dlg *)dv;
-    [d->target performSelector:d->action
-     withObject:[NSNumber numberWithInt:value]];
-}
-
-void dlg_coloursel_start(union control *ctrl, void *dv,
-                        int r, int g, int b)
-{
-    /* FIXME */
-}
-
-int dlg_coloursel_results(union control *ctrl, void *dv,
-                         int *r, int *g, int *b)
-{
-    return 0; /* FIXME */
-}
-
-void dlg_refresh(union control *ctrl, void *dv)
-{
-    struct fe_dlg *d = (struct fe_dlg *)dv;
-    struct fe_ctrl *c;
-
-    if (ctrl) {
-       if (ctrl->generic.handler != NULL)
-           ctrl->generic.handler(ctrl, d, d->data, EVENT_REFRESH);
-    } else {
-       int i;
-
-       for (i = 0; (c = index234(d->byctrl, i)) != NULL; i++) {
-           assert(c->ctrl != NULL);
-           if (c->ctrl->generic.handler != NULL)
-               c->ctrl->generic.handler(c->ctrl, d,
-                                        d->data, EVENT_REFRESH);
-       }
-    }
-}
diff --git a/macosx/osxdlg.m b/macosx/osxdlg.m
deleted file mode 100644 (file)
index 84a761f..0000000
+++ /dev/null
@@ -1,509 +0,0 @@
-/*
- * osxdlg.m: various PuTTY dialog boxes for OS X.
- */
-
-#import <Cocoa/Cocoa.h>
-#include "putty.h"
-#include "storage.h"
-#include "dialog.h"
-#include "osxclass.h"
-
-/*
- * The `ConfigWindow' class is used to start up a new PuTTY
- * session.
- */
-
-@class ConfigTree;
-@interface ConfigTree : NSObject
-{
-    NSString **paths;
-    int *levels;
-    int nitems, itemsize;
-}
-- (void)addPath:(char *)path;
-@end
-
-@implementation ConfigTree
-- (id)init
-{
-    self = [super init];
-    paths = NULL;
-    levels = NULL;
-    nitems = itemsize = 0;
-    return self;
-}
-- (void)addPath:(char *)path
-{
-    if (nitems >= itemsize) {
-       itemsize += 32;
-       paths = sresize(paths, itemsize, NSString *);
-       levels = sresize(levels, itemsize, int);
-    }
-    paths[nitems] = [[NSString stringWithCString:path] retain];
-    levels[nitems] = ctrl_path_elements(path) - 1;
-    nitems++;
-}
-- (void)dealloc
-{
-    int i;
-
-    for (i = 0; i < nitems; i++)
-       [paths[i] release];
-
-    sfree(paths);
-    sfree(levels);
-
-    [super dealloc];
-}
-- (id)iterateChildren:(int)index ofItem:(id)item count:(int *)count
-{
-    int i, plevel;
-
-    if (item) {
-       for (i = 0; i < nitems; i++)
-           if (paths[i] == item)
-               break;
-       assert(i < nitems);
-       plevel = levels[i];
-       i++;
-    } else {
-       i = 0;
-       plevel = -1;
-    }
-
-    if (count)
-       *count = 0;
-
-    while (index > 0) {
-       if (i >= nitems || levels[i] != plevel+1)
-           return nil;
-       if (count)
-           (*count)++;
-       do {
-           i++;
-       } while (i < nitems && levels[i] > plevel+1);
-       index--;
-    }
-
-    return paths[i];
-}
-- (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item
-{
-    return [self iterateChildren:index ofItem:item count:NULL];
-}
-- (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
-{
-    int count = 0;
-    /* pass nitems+1 to ensure we run off the end */
-    [self iterateChildren:nitems+1 ofItem:item count:&count];
-    return count;
-}
-- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
-{
-    return [self outlineView:outlineView numberOfChildrenOfItem:item] > 0;
-}
-- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
-{
-    /*
-     * Trim off all path elements except the last one.
-     */
-    NSArray *components = [item componentsSeparatedByString:@"/"];
-    return [components objectAtIndex:[components count]-1];
-}
-@end
-
-@implementation ConfigWindow
-- (id)initWithConfig:(Config)aCfg
-{
-    NSScrollView *scrollview;
-    NSTableColumn *col;
-    ConfigTree *treedata;
-    int by = 0, mby = 0;
-    int wmin = 0;
-    int hmin = 0;
-    int panelht = 0;
-
-    ctrlbox = ctrl_new_box();
-    setup_config_box(ctrlbox, FALSE /*midsession*/, aCfg.protocol,
-                    0 /* protcfginfo */);
-    unix_setup_config_box(ctrlbox, FALSE /*midsession*/, aCfg.protocol);
-
-    cfg = aCfg;                               /* structure copy */
-
-    self = [super initWithContentRect:NSMakeRect(0,0,300,300)
-           styleMask:(NSTitledWindowMask | NSMiniaturizableWindowMask |
-                      NSClosableWindowMask)
-           backing:NSBackingStoreBuffered
-           defer:YES];
-    [self setTitle:@"PuTTY Configuration"];
-
-    [self setIgnoresMouseEvents:NO];
-
-    dv = fe_dlg_init(&cfg, self, self, @selector(configBoxFinished:));
-
-    scrollview = [[NSScrollView alloc] initWithFrame:NSMakeRect(20,20,10,10)];
-    treeview = [[NSOutlineView alloc] initWithFrame:[scrollview frame]];
-    [scrollview setBorderType:NSLineBorder];
-    [scrollview setDocumentView:treeview];
-    [[self contentView] addSubview:scrollview];
-    [scrollview setHasVerticalScroller:YES];
-    [scrollview setAutohidesScrollers:YES];
-    /* FIXME: the below is untested. Test it then remove this notice. */
-    [treeview setAllowsColumnReordering:NO];
-    [treeview setAllowsColumnResizing:NO];
-    [treeview setAllowsMultipleSelection:NO];
-    [treeview setAllowsEmptySelection:NO];
-    [treeview setAllowsColumnSelection:YES];
-
-    treedata = [[[ConfigTree alloc] init] retain];
-
-    col = [[NSTableColumn alloc] initWithIdentifier:nil];
-    [treeview addTableColumn:col];
-    [treeview setOutlineTableColumn:col];
-
-    [[treeview headerView] setFrame:NSMakeRect(0,0,0,0)];
-
-    /*
-     * Create the controls.
-     */
-    {
-       int i;
-       char *path = NULL;
-
-       for (i = 0; i < ctrlbox->nctrlsets; i++) {
-           struct controlset *s = ctrlbox->ctrlsets[i];
-           int mw, mh;
-
-           if (!*s->pathname) {
-
-               create_ctrls(dv, [self contentView], s, &mw, &mh);
-
-               by += 20 + mh;
-
-               if (wmin < mw + 40)
-                   wmin = mw + 40;
-           } else {
-               int j = path ? ctrl_path_compare(s->pathname, path) : 0;
-
-               if (j != INT_MAX) {    /* add to treeview, start new panel */
-                   char *c;
-
-                   /*
-                    * We expect never to find an implicit path
-                    * component. For example, we expect never to
-                    * see A/B/C followed by A/D/E, because that
-                    * would _implicitly_ create A/D. All our path
-                    * prefixes are expected to contain actual
-                    * controls and be selectable in the treeview;
-                    * so we would expect to see A/D _explicitly_
-                    * before encountering A/D/E.
-                    */
-                   assert(j == ctrl_path_elements(s->pathname) - 1);
-
-                   c = strrchr(s->pathname, '/');
-                   if (!c)
-                       c = s->pathname;
-                   else
-                       c++;
-
-                   [treedata addPath:s->pathname];
-                   path = s->pathname;
-
-                   panelht = 0;
-               }
-
-               create_ctrls(dv, [self contentView], s, &mw, &mh);
-               if (wmin < mw + 3*20+150)
-                   wmin = mw + 3*20+150;
-               panelht += mh + 20;
-               if (hmin < panelht - 20)
-                   hmin = panelht - 20;
-           }
-       }
-    }
-
-    {
-       int i;
-       NSRect r;
-
-       [treeview setDataSource:treedata];
-       for (i = [treeview numberOfRows]; i-- ;)
-           [treeview expandItem:[treeview itemAtRow:i] expandChildren:YES];
-
-       [treeview sizeToFit];
-       r = [treeview frame];
-       if (hmin < r.size.height)
-           hmin = r.size.height;
-    }
-
-    [self setContentSize:NSMakeSize(wmin, hmin+60+by)];
-    [scrollview setFrame:NSMakeRect(20, 40+by, 150, hmin)];
-    [treeview setDelegate:self];
-    mby = by;
-
-    /*
-     * Now place the controls.
-     */
-    {
-       int i;
-       char *path = NULL;
-       panelht = 0;
-
-       for (i = 0; i < ctrlbox->nctrlsets; i++) {
-           struct controlset *s = ctrlbox->ctrlsets[i];
-
-           if (!*s->pathname) {
-               by -= VSPACING + place_ctrls(dv, s, 20, by, wmin-40);
-           } else {
-               if (!path || strcmp(s->pathname, path))
-                   panelht = 0;
-
-               panelht += VSPACING + place_ctrls(dv, s, 2*20+150,
-                                                 40+mby+hmin-panelht,
-                                                 wmin - (3*20+150));
-
-               path = s->pathname;
-           }
-       }
-    }
-
-    select_panel(dv, ctrlbox, [[treeview itemAtRow:0] cString]);
-
-    [treeview reloadData];
-
-    dlg_refresh(NULL, dv);
-
-    [self center];                    /* :-) */
-
-    return self;
-}
-- (void)configBoxFinished:(id)object
-{
-    int ret = [object intValue];       /* it'll be an NSNumber */
-    if (ret) {
-       [controller performSelectorOnMainThread:
-        @selector(newSessionWithConfig:)
-        withObject:[NSData dataWithBytes:&cfg length:sizeof(cfg)]
-        waitUntilDone:NO];
-    }
-    [self close];
-}
-- (void)outlineViewSelectionDidChange:(NSNotification *)notification
-{
-    const char *path = [[treeview itemAtRow:[treeview selectedRow]] cString];
-    select_panel(dv, ctrlbox, path);
-}
-- (BOOL)outlineView:(NSOutlineView *)outlineView
-    shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item
-{
-    return NO;                        /* no editing! */
-}
-@end
-
-/* ----------------------------------------------------------------------
- * Various special-purpose dialog boxes.
- */
-
-struct appendstate {
-    void (*callback)(void *ctx, int result);
-    void *ctx;
-};
-
-static void askappend_callback(void *ctx, int result)
-{
-    struct appendstate *state = (struct appendstate *)ctx;
-
-    state->callback(state->ctx, (result == NSAlertFirstButtonReturn ? 2 :
-                                result == NSAlertSecondButtonReturn ? 1 : 0));
-    sfree(state);
-}
-
-int askappend(void *frontend, Filename filename,
-             void (*callback)(void *ctx, int result), void *ctx)
-{
-    static const char msgtemplate[] =
-       "The session log file \"%s\" already exists. "
-       "You can overwrite it with a new session log, "
-       "append your session log to the end of it, "
-       "or disable session logging for this session.";
-
-    char *text;
-    SessionWindow *win = (SessionWindow *)frontend;
-    struct appendstate *state;
-    NSAlert *alert;
-
-    text = dupprintf(msgtemplate, filename.path);
-
-    state = snew(struct appendstate);
-    state->callback = callback;
-    state->ctx = ctx;
-
-    alert = [[NSAlert alloc] init];
-    [alert setInformativeText:[NSString stringWithCString:text]];
-    [alert addButtonWithTitle:@"Overwrite"];
-    [alert addButtonWithTitle:@"Append"];
-    [alert addButtonWithTitle:@"Disable"];
-    [win startAlert:alert withCallback:askappend_callback andCtx:state];
-
-    return -1;
-}
-
-struct algstate {
-    void (*callback)(void *ctx, int result);
-    void *ctx;
-};
-
-static void askalg_callback(void *ctx, int result)
-{
-    struct algstate *state = (struct algstate *)ctx;
-
-    state->callback(state->ctx, result == NSAlertFirstButtonReturn);
-    sfree(state);
-}
-
-int askalg(void *frontend, const char *algtype, const char *algname,
-          void (*callback)(void *ctx, int result), void *ctx)
-{
-    static const char msg[] =
-       "The first %s supported by the server is "
-       "%s, which is below the configured warning threshold.\n"
-       "Continue with connection?";
-
-    char *text;
-    SessionWindow *win = (SessionWindow *)frontend;
-    struct algstate *state;
-    NSAlert *alert;
-
-    text = dupprintf(msg, algtype, algname);
-
-    state = snew(struct algstate);
-    state->callback = callback;
-    state->ctx = ctx;
-
-    alert = [[NSAlert alloc] init];
-    [alert setInformativeText:[NSString stringWithCString:text]];
-    [alert addButtonWithTitle:@"Yes"];
-    [alert addButtonWithTitle:@"No"];
-    [win startAlert:alert withCallback:askalg_callback andCtx:state];
-
-    return -1;
-}
-
-struct hostkeystate {
-    char *host, *keytype, *keystr;
-    int port;
-    void (*callback)(void *ctx, int result);
-    void *ctx;
-};
-
-static void verify_ssh_host_key_callback(void *ctx, int result)
-{
-    struct hostkeystate *state = (struct hostkeystate *)ctx;
-
-    if (result == NSAlertThirdButtonReturn)   /* `Accept' */
-       store_host_key(state->host, state->port,
-                      state->keytype, state->keystr);
-    state->callback(state->ctx, result != NSAlertFirstButtonReturn);
-    sfree(state->host);
-    sfree(state->keytype);
-    sfree(state->keystr);
-    sfree(state);
-}
-
-int verify_ssh_host_key(void *frontend, char *host, int port,
-                        const char *keytype, char *keystr, char *fingerprint,
-                        void (*callback)(void *ctx, int result), void *ctx)
-{
-    static const char absenttxt[] =
-       "The server's host key is not cached. You have no guarantee "
-       "that the server is the computer you think it is.\n"
-       "The server's %s key fingerprint is:\n"
-       "%s\n"
-       "If you trust this host, press \"Accept\" to add the key to "
-       "PuTTY's cache and carry on connecting.\n"
-       "If you want to carry on connecting just once, without "
-       "adding the key to the cache, press \"Connect Once\".\n"
-       "If you do not trust this host, press \"Cancel\" to abandon the "
-       "connection.";
-    static const char wrongtxt[] =
-       "WARNING - POTENTIAL SECURITY BREACH!\n"
-       "The server's host key does not match the one PuTTY has "
-       "cached. This means that either the server administrator "
-       "has changed the host key, or you have actually connected "
-       "to another computer pretending to be the server.\n"
-       "The new %s key fingerprint is:\n"
-       "%s\n"
-       "If you were expecting this change and trust the new key, "
-       "press \"Accept\" to update PuTTY's cache and continue connecting.\n"
-       "If you want to carry on connecting but without updating "
-       "the cache, press \"Connect Once\".\n"
-       "If you want to abandon the connection completely, press "
-       "\"Cancel\" to cancel. Pressing \"Cancel\" is the ONLY guaranteed "
-       "safe choice.";
-
-    int ret;
-    char *text;
-    SessionWindow *win = (SessionWindow *)frontend;
-    struct hostkeystate *state;
-    NSAlert *alert;
-
-    /*
-     * Verify the key.
-     */
-    ret = verify_host_key(host, port, keytype, keystr);
-
-    if (ret == 0)
-       return 1;
-
-    text = dupprintf((ret == 2 ? wrongtxt : absenttxt), keytype, fingerprint);
-
-    state = snew(struct hostkeystate);
-    state->callback = callback;
-    state->ctx = ctx;
-    state->host = dupstr(host);
-    state->port = port;
-    state->keytype = dupstr(keytype);
-    state->keystr = dupstr(keystr);
-
-    alert = [[NSAlert alloc] init];
-    [alert setInformativeText:[NSString stringWithCString:text]];
-    [alert addButtonWithTitle:@"Cancel"];
-    [alert addButtonWithTitle:@"Connect Once"];
-    [alert addButtonWithTitle:@"Accept"];
-    [win startAlert:alert withCallback:verify_ssh_host_key_callback
-     andCtx:state];
-
-    return -1;
-}
-
-void old_keyfile_warning(void)
-{
-    /*
-     * This should never happen on OS X. We hope.
-     */
-}
-
-static void connection_fatal_callback(void *ctx, int result)
-{
-    SessionWindow *win = (SessionWindow *)ctx;
-
-    [win endSession:FALSE];
-}
-
-void connection_fatal(void *frontend, const char *p, ...)
-{
-    SessionWindow *win = (SessionWindow *)frontend;
-    va_list ap;
-    char *msg;
-    NSAlert *alert;
-
-    va_start(ap, p);
-    msg = dupvprintf(p, ap);
-    va_end(ap);
-
-    alert = [[NSAlert alloc] init];
-    [alert setInformativeText:[NSString stringWithCString:msg]];
-    [alert addButtonWithTitle:@"Proceed"];
-    [win startAlert:alert withCallback:connection_fatal_callback
-     andCtx:win];
-}
diff --git a/macosx/osxmain.m b/macosx/osxmain.m
deleted file mode 100644 (file)
index 2ac772a..0000000
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- * osxmain.m: main-program file of Mac OS X PuTTY.
- */
-
-#import <Cocoa/Cocoa.h>
-
-#define PUTTY_DO_GLOBALS              /* actually _define_ globals */
-
-#include "putty.h"
-#include "osxclass.h"
-
-/* ----------------------------------------------------------------------
- * Global variables.
- */
-
-AppController *controller;
-
-/* ----------------------------------------------------------------------
- * Miscellaneous elements of the interface to the cross-platform
- * and Unix PuTTY code.
- */
-
-char *platform_get_x_display(void) {
-    return NULL;
-}
-
-FontSpec platform_default_fontspec(const char *name)
-{
-    FontSpec ret;
-    /* FIXME */
-    return ret;
-}
-
-Filename platform_default_filename(const char *name)
-{
-    Filename ret;
-    if (!strcmp(name, "LogFileName"))
-       strcpy(ret.path, "putty.log");
-    else
-       *ret.path = '\0';
-    return ret;
-}
-
-char *platform_default_s(const char *name)
-{
-    return NULL;
-}
-
-int platform_default_i(const char *name, int def)
-{
-    if (!strcmp(name, "CloseOnExit"))
-       return 2;  /* maps to FORCE_ON after painful rearrangement :-( */
-    return def;
-}
-
-char *x_get_default(const char *key)
-{
-    return NULL;                      /* this is a stub */
-}
-
-static void commonfatalbox(const char *p, va_list ap)
-{
-    char errorbuf[2048];
-    NSAlert *alert;
-
-    /*
-     * We may have come here because we ran out of memory, in which
-     * case it's entirely likely that that further memory
-     * allocations will fail. So (a) we use vsnprintf to format the
-     * error message rather than the usual dupvprintf; and (b) we
-     * have a fallback way to get the message out via stderr if
-     * even creating an NSAlert fails.
-     */
-    vsnprintf(errorbuf, lenof(errorbuf), p, ap);
-
-    alert = [NSAlert alloc];
-    if (!alert) {
-       fprintf(stderr, "fatal error (and NSAlert failed): %s\n", errorbuf);
-    } else {
-       alert = [[alert init] autorelease];
-       [alert addButtonWithTitle:@"Terminate"];
-       [alert setInformativeText:[NSString stringWithCString:errorbuf]];
-       [alert runModal];
-    }
-    exit(1);
-}
-
-void nonfatal(void *frontend, const char *p, ...)
-{
-    char *errorbuf;
-    NSAlert *alert;
-    va_list ap;
-
-    va_start(ap, p);
-    errorbuf = dupvprintf(p, ap);
-    va_end(ap);
-
-    alert = [[[NSAlert alloc] init] autorelease];
-    [alert addButtonWithTitle:@"Error"];
-    [alert setInformativeText:[NSString stringWithCString:errorbuf]];
-    [alert runModal];
-
-    sfree(errorbuf);
-}
-
-void fatalbox(const char *p, ...)
-{
-    va_list ap;
-    va_start(ap, p);
-    commonfatalbox(p, ap);
-    va_end(ap);
-}
-
-void modalfatalbox(const char *p, ...)
-{
-    va_list ap;
-    va_start(ap, p);
-    commonfatalbox(p, ap);
-    va_end(ap);
-}
-
-void cmdline_error(const char *p, ...)
-{
-    va_list ap;
-    fprintf(stderr, "%s: ", appname);
-    va_start(ap, p);
-    vfprintf(stderr, p, ap);
-    va_end(ap);
-    fputc('\n', stderr);
-    exit(1);
-}
-
-/*
- * Clean up and exit.
- */
-void cleanup_exit(int code)
-{
-    /*
-     * Clean up.
-     */
-    sk_cleanup();
-    random_save_seed();
-    exit(code);
-}
-
-/* ----------------------------------------------------------------------
- * Tiny extension to NSMenuItem which carries a payload of a `void
- * *', allowing several menu items to invoke the same message but
- * pass different data through it.
- */
-@interface DataMenuItem : NSMenuItem
-{
-    void *payload;
-}
-- (void)setPayload:(void *)d;
-- (void *)getPayload;
-@end
-@implementation DataMenuItem
-- (void)setPayload:(void *)d
-{
-    payload = d;
-}
-- (void *)getPayload
-{
-    return payload;
-}
-@end
-
-/* ----------------------------------------------------------------------
- * Utility routines for constructing OS X menus.
- */
-
-NSMenu *newmenu(const char *title)
-{
-    return [[[NSMenu allocWithZone:[NSMenu menuZone]]
-            initWithTitle:[NSString stringWithCString:title]]
-           autorelease];
-}
-
-NSMenu *newsubmenu(NSMenu *parent, const char *title)
-{
-    NSMenuItem *item;
-    NSMenu *child;
-
-    item = [[[NSMenuItem allocWithZone:[NSMenu menuZone]]
-            initWithTitle:[NSString stringWithCString:title]
-            action:NULL
-            keyEquivalent:@""]
-           autorelease];
-    child = newmenu(title);
-    [item setEnabled:YES];
-    [item setSubmenu:child];
-    [parent addItem:item];
-    return child;
-}
-
-id initnewitem(NSMenuItem *item, NSMenu *parent, const char *title,
-              const char *key, id target, SEL action)
-{
-    unsigned mask = NSCommandKeyMask;
-
-    if (key[strcspn(key, "-")]) {
-       while (*key && *key != '-') {
-           int c = tolower((unsigned char)*key);
-           if (c == 's') {
-               mask |= NSShiftKeyMask;
-           } else if (c == 'o' || c == 'a') {
-               mask |= NSAlternateKeyMask;
-           }
-           key++;
-       }
-       if (*key)
-           key++;
-    }
-
-    item = [[item initWithTitle:[NSString stringWithCString:title]
-            action:NULL
-            keyEquivalent:[NSString stringWithCString:key]]
-           autorelease];
-
-    if (*key)
-       [item setKeyEquivalentModifierMask: mask];
-
-    [item setEnabled:YES];
-    [item setTarget:target];
-    [item setAction:action];
-
-    [parent addItem:item];
-
-    return item;
-}
-
-NSMenuItem *newitem(NSMenu *parent, char *title, char *key,
-                   id target, SEL action)
-{
-    return initnewitem([NSMenuItem allocWithZone:[NSMenu menuZone]],
-                      parent, title, key, target, action);
-}
-
-/* ----------------------------------------------------------------------
- * AppController: the object which receives the messages from all
- * menu selections that aren't standard OS X functions.
- */
-@implementation AppController
-
-- (id)init
-{
-    self = [super init];
-    timer = NULL;
-    return self;
-}
-
-- (void)newTerminal:(id)sender
-{
-    id win;
-    Config cfg;
-
-    do_defaults(NULL, &cfg);
-
-    cfg.protocol = -1;                /* PROT_TERMINAL */
-
-    win = [[SessionWindow alloc] initWithConfig:cfg];
-    [win makeKeyAndOrderFront:self];
-}
-
-- (void)newSessionConfig:(id)sender
-{
-    id win;
-    Config cfg;
-
-    do_defaults(NULL, &cfg);
-
-    win = [[ConfigWindow alloc] initWithConfig:cfg];
-    [win makeKeyAndOrderFront:self];
-}
-
-- (void)newSessionWithConfig:(id)vdata
-{
-    id win;
-    Config cfg;
-    NSData *data = (NSData *)vdata;
-
-    assert([data length] == sizeof(cfg));
-    [data getBytes:&cfg];
-
-    win = [[SessionWindow alloc] initWithConfig:cfg];
-    [win makeKeyAndOrderFront:self];
-}
-
-- (NSMenu *)applicationDockMenu:(NSApplication *)sender
-{
-    NSMenu *menu = newmenu("Dock Menu");
-    /*
-     * FIXME: Add some useful things to this, probably including
-     * the saved session list.
-     */
-    return menu;
-}
-
-- (void)timerFired:(id)sender
-{
-    long now, next;
-
-    assert(sender == timer);
-
-    /* `sender' is the timer itself, so its userInfo is an NSNumber. */
-    now = [(NSNumber *)[sender userInfo] longValue];
-
-    [sender invalidate];
-
-    timer = NULL;
-
-    if (run_timers(now, &next))
-       [self setTimer:next];
-}
-
-- (void)setTimer:(long)next
-{
-    long interval = next - GETTICKCOUNT();
-    float finterval;
-
-    if (interval <= 0)
-       interval = 1;                  /* just in case */
-
-    finterval = interval / (float)TICKSPERSEC;
-
-    if (timer) {
-       [timer invalidate];
-    }
-
-    timer = [NSTimer scheduledTimerWithTimeInterval:finterval
-            target:self selector:@selector(timerFired:)
-            userInfo:[NSNumber numberWithLong:next] repeats:NO];
-}
-
-@end
-
-void timer_change_notify(long next)
-{
-    [controller setTimer:next];
-}
-
-/* ----------------------------------------------------------------------
- * Annoyingly, it looks as if I have to actually subclass
- * NSApplication if I want to catch NSApplicationDefined events. So
- * here goes.
- */
-@interface MyApplication : NSApplication
-{
-}
-@end
-@implementation MyApplication
-- (void)sendEvent:(NSEvent *)ev
-{
-    if ([ev type] == NSApplicationDefined)
-       osxsel_process_results();
-
-    [super sendEvent:ev];
-}    
-@end
-
-/* ----------------------------------------------------------------------
- * Main program. Constructs the menus and runs the application.
- */
-int main(int argc, char **argv)
-{
-    NSAutoreleasePool *pool;
-    NSMenu *menu;
-    NSMenuItem *item;
-    NSImage *icon;
-
-    pool = [[NSAutoreleasePool alloc] init];
-
-    icon = [NSImage imageNamed:@"NSApplicationIcon"];
-    [MyApplication sharedApplication];
-    [NSApp setApplicationIconImage:icon];
-
-    controller = [[[AppController alloc] init] autorelease];
-    [NSApp setDelegate:controller];
-
-    [NSApp setMainMenu: newmenu("Main Menu")];
-
-    menu = newsubmenu([NSApp mainMenu], "Apple Menu");
-    [NSApp setServicesMenu:newsubmenu(menu, "Services")];
-    [menu addItem:[NSMenuItem separatorItem]];
-    item = newitem(menu, "Hide PuTTY", "h", NSApp, @selector(hide:));
-    item = newitem(menu, "Hide Others", "o-h", NSApp, @selector(hideOtherApplications:));
-    item = newitem(menu, "Show All", "", NSApp, @selector(unhideAllApplications:));
-    [menu addItem:[NSMenuItem separatorItem]];
-    item = newitem(menu, "Quit", "q", NSApp, @selector(terminate:));
-    [NSApp setAppleMenu: menu];
-
-    menu = newsubmenu([NSApp mainMenu], "File");
-    item = newitem(menu, "New", "n", NULL, @selector(newSessionConfig:));
-    item = newitem(menu, "New Terminal", "t", NULL, @selector(newTerminal:));
-    item = newitem(menu, "Close", "w", NULL, @selector(performClose:));
-
-    menu = newsubmenu([NSApp mainMenu], "Window");
-    [NSApp setWindowsMenu: menu];
-    item = newitem(menu, "Minimise Window", "m", NULL, @selector(performMiniaturize:));
-
-//    menu = newsubmenu([NSApp mainMenu], "Help");
-//    item = newitem(menu, "PuTTY Help", "?", NSApp, @selector(showHelp:));
-
-    /*
-     * Start up the sub-thread doing select().
-     */
-    osxsel_init();
-
-    /*
-     * Start up networking.
-     */
-    sk_init();
-
-    /*
-     * FIXME: To make initial debugging more convenient I'm going
-     * to start by opening a session window unconditionally. This
-     * will probably change later on.
-     */
-    [controller newSessionConfig:nil];
-
-    [NSApp run];
-    [pool release];
-
-    return 0;
-}
diff --git a/macosx/osxsel.m b/macosx/osxsel.m
deleted file mode 100644 (file)
index eac6028..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * osxsel.m: OS X implementation of the front end interface to uxsel.
- */
-
-#import <Cocoa/Cocoa.h>
-#include <unistd.h>
-#include "putty.h"
-#include "osxclass.h"
-
-/*
- * The unofficial Cocoa FAQ at
- *
- *   http://www.alastairs-place.net/cocoa/faq.txt
- * 
- * says that Cocoa has the native ability to be given an fd and
- * tell you when it becomes readable, but cannot tell you when it
- * becomes _writable_. This is unacceptable to PuTTY, which depends
- * for correct functioning on being told both. Therefore, I can't
- * use the Cocoa native mechanism.
- * 
- * Instead, I'm going to resort to threads. I start a second thread
- * whose job is to do selects. At the termination of every select,
- * it posts a Cocoa event into the main thread's event queue, so
- * that the main thread gets select results interleaved with other
- * GUI operations. Communication from the main thread _to_ the
- * select thread is performed by writing to a pipe whose other end
- * is one of the file descriptors being selected on. (This is the
- * only sensible way, because we have to be able to interrupt a
- * select in order to provide a new fd list.)
- */
-
-/*
- * In more detail, the select thread must:
- * 
- *  - start off by listening to _just_ the pipe, waiting to be told
- *    to begin a select.
- * 
- *  - when it receives the `start' command, it should read the
- *    shared uxsel data (which is protected by a mutex), set up its
- *    select, and begin it.
- * 
- *  - when the select terminates, it should write the results
- *    (perhaps minus the inter-thread pipe if it's there) into
- *    shared memory and dispatch a GUI event to let the main thread
- *    know.
- * 
- *  - the main thread will then think about it, do some processing,
- *    and _then_ send a command saying `now restart select'. Before
- *    sending that command it might easily have tinkered with the
- *    uxsel structures, which is why it waited before sending it.
- * 
- *  - EOF on the inter-thread pipe, of course, means the process
- *    has finished completely, so the select thread terminates.
- * 
- *  - The main thread may wish to adjust the uxsel settings in the
- *    middle of a select. In this situation it first writes the new
- *    data to the shared memory area, then notifies the select
- *    thread by writing to the inter-thread pipe.
- * 
- * So the upshot is that the sequence of operations performed in
- * the select thread must be:
- * 
- *  - read a byte from the pipe (which may block)
- * 
- *  - read the shared uxsel data and perform a select
- * 
- *  - notify the main thread of interesting select results (if any)
- * 
- *  - loop round again from the top.
- * 
- * This is sufficient. Notifying the select thread asynchronously
- * by writing to the pipe will cause its select to terminate and
- * another to begin immediately without blocking. If the select
- * thread's select terminates due to network data, its subsequent
- * pipe read will block until the main thread is ready to let it
- * loose again.
- */
-
-static int osxsel_pipe[2];
-
-static NSLock *osxsel_inlock;
-static fd_set osxsel_rfds_in;
-static fd_set osxsel_wfds_in;
-static fd_set osxsel_xfds_in;
-static int osxsel_inmax;
-
-static NSLock *osxsel_outlock;
-static fd_set osxsel_rfds_out;
-static fd_set osxsel_wfds_out;
-static fd_set osxsel_xfds_out;
-static int osxsel_outmax;
-
-static int inhibit_start_select;
-
-/*
- * NSThread requires an object method as its thread procedure, so
- * here I define a trivial holding class.
- */
-@class OSXSel;
-@interface OSXSel : NSObject
-{
-}
-- (void)runThread:(id)arg;
-@end
-@implementation OSXSel
-- (void)runThread:(id)arg
-{
-    char c;
-    fd_set r, w, x;
-    int n, ret;
-    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
-    while (1) {
-       /*
-        * Read one byte from the pipe.
-        */
-       ret = read(osxsel_pipe[0], &c, 1);
-
-       if (ret <= 0)
-           return;                    /* terminate the thread */
-
-       /*
-        * Now set up the select data.
-        */
-       [osxsel_inlock lock];
-       memcpy(&r, &osxsel_rfds_in, sizeof(fd_set));
-       memcpy(&w, &osxsel_wfds_in, sizeof(fd_set));
-       memcpy(&x, &osxsel_xfds_in, sizeof(fd_set));
-       n = osxsel_inmax;
-       [osxsel_inlock unlock];
-       FD_SET(osxsel_pipe[0], &r);
-       if (n < osxsel_pipe[0]+1)
-           n = osxsel_pipe[0]+1;
-
-       /*
-        * Perform the select.
-        */
-       ret = select(n, &r, &w, &x, NULL);
-
-       /*
-        * Detect the one special case in which the only
-        * interesting fd was the inter-thread pipe. In that
-        * situation only we are interested - the main thread will
-        * not be!
-        */
-       if (ret == 1 && FD_ISSET(osxsel_pipe[0], &r))
-           continue;                  /* just loop round again */
-
-       /*
-        * Write the select results to shared data.
-        * 
-        * I _think_ we don't need this data to be lock-protected:
-        * it won't be read by the main thread until after we send
-        * a message indicating that we've finished writing it, and
-        * we won't start another select (hence potentially writing
-        * it again) until the main thread notifies us in return.
-        * 
-        * However, I'm scared of multithreading and not totally
-        * convinced of my reasoning, so I'm going to lock it
-        * anyway.
-        */
-       [osxsel_outlock lock];
-       memcpy(&osxsel_rfds_out, &r, sizeof(fd_set));
-       memcpy(&osxsel_wfds_out, &w, sizeof(fd_set));
-       memcpy(&osxsel_xfds_out, &x, sizeof(fd_set));
-       osxsel_outmax = n;
-       [osxsel_outlock unlock];
-
-       /*
-        * Post a message to the main thread's message queue
-        * telling it that select data is available.
-        */
-       [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined
-                         location:NSMakePoint(0,0)
-                         modifierFlags:0
-                         timestamp:0
-                         windowNumber:0
-                         context:nil
-                         subtype:0
-                         data1:0
-                         data2:0]
-        atStart:NO];
-    }
-
-    [pool release];
-}
-@end
-
-void osxsel_init(void)
-{
-    uxsel_init();
-
-    if (pipe(osxsel_pipe) < 0) {
-       fatalbox("Unable to set up inter-thread pipe for select");
-    }
-    [NSThread detachNewThreadSelector:@selector(runThread:)
-       toTarget:[[[OSXSel alloc] init] retain] withObject:nil];
-    /*
-     * Also initialise (i.e. clear) the input fd_sets. Need not
-     * start a select just yet - the select thread will block until
-     * we have at least one fd for it!
-     */
-    FD_ZERO(&osxsel_rfds_in);
-    FD_ZERO(&osxsel_wfds_in);
-    FD_ZERO(&osxsel_xfds_in);
-    osxsel_inmax = 0;
-    /*
-     * Initialise the mutex locks used to protect the data passed
-     * between threads.
-     */
-    osxsel_inlock = [[[NSLock alloc] init] retain];
-    osxsel_outlock = [[[NSLock alloc] init] retain];
-}
-
-static void osxsel_start_select(void)
-{
-    char c = 'g';                     /* for `Go!' :-) but it's never used */
-
-    if (!inhibit_start_select)
-       write(osxsel_pipe[1], &c, 1);
-}
-
-int uxsel_input_add(int fd, int rwx)
-{
-    /*
-     * Add the new fd to the appropriate input fd_sets, then write
-     * to the inter-thread pipe.
-     */
-    [osxsel_inlock lock];
-    if (rwx & 1)
-       FD_SET(fd, &osxsel_rfds_in);
-    else
-       FD_CLR(fd, &osxsel_rfds_in);
-    if (rwx & 2)
-       FD_SET(fd, &osxsel_wfds_in);
-    else
-       FD_CLR(fd, &osxsel_wfds_in);
-    if (rwx & 4)
-       FD_SET(fd, &osxsel_xfds_in);
-    else
-       FD_CLR(fd, &osxsel_xfds_in);
-    if (osxsel_inmax < fd+1)
-       osxsel_inmax = fd+1;
-    [osxsel_inlock unlock];
-    osxsel_start_select();
-
-    /*
-     * We must return an `id' which will be passed back to us at
-     * the time of uxsel_input_remove. Since we have no need to
-     * store ids in that sense, we might as well go with the fd
-     * itself.
-     */
-    return fd;
-}
-
-void uxsel_input_remove(int id)
-{
-    /*
-     * Remove the fd from all the input fd_sets. In this
-     * implementation, the simplest way to do that is to call
-     * uxsel_input_add with rwx==0!
-     */
-    uxsel_input_add(id, 0);
-}
-
-/*
- * Function called in the main thread to process results. It will
- * have to read the output fd_sets, go through them, call back to
- * uxsel with the results, and then write to the inter-thread pipe.
- * 
- * This function will have to be called from an event handler in
- * osxmain.m, which will therefore necessarily contain a small part
- * of this mechanism (along with calling osxsel_init).
- */
-void osxsel_process_results(void)
-{
-    int i;
-
-    /*
-     * We must write to the pipe to start a fresh select _even if_
-     * there were no changes. So for efficiency, we set a flag here
-     * which inhibits uxsel_input_{add,remove} from writing to the
-     * pipe; then once we finish processing, we clear the flag
-     * again and write a single byte ourselves. It's cleaner,
-     * because it wakes up the select thread fewer times.
-     */
-    inhibit_start_select = TRUE;
-
-    [osxsel_outlock lock];
-
-    for (i = 0; i < osxsel_outmax; i++) {
-       if (FD_ISSET(i, &osxsel_xfds_out))
-           select_result(i, 4);
-    }
-    for (i = 0; i < osxsel_outmax; i++) {
-       if (FD_ISSET(i, &osxsel_rfds_out))
-           select_result(i, 1);
-    }
-    for (i = 0; i < osxsel_outmax; i++) {
-       if (FD_ISSET(i, &osxsel_wfds_out))
-           select_result(i, 2);
-    }
-
-    [osxsel_outlock unlock];
-
-    inhibit_start_select = FALSE;
-    osxsel_start_select();
-}
diff --git a/macosx/osxwin.m b/macosx/osxwin.m
deleted file mode 100644 (file)
index 0629136..0000000
+++ /dev/null
@@ -1,1227 +0,0 @@
-/*
- * osxwin.m: code to manage a session window in Mac OS X PuTTY.
- */
-
-#import <Cocoa/Cocoa.h>
-#include "putty.h"
-#include "terminal.h"
-#include "osxclass.h"
-
-/* Colours come in two flavours: configurable, and xterm-extended. */
-#define NCFGCOLOURS (lenof(((Config *)0)->colours))
-#define NEXTCOLOURS 240 /* 216 colour-cube plus 24 shades of grey */
-#define NALLCOLOURS (NCFGCOLOURS + NEXTCOLOURS)
-
-/*
- * The key component of the per-session data is the SessionWindow
- * class. A pointer to this is used as the frontend handle, to be
- * passed to all the platform-independent subsystems that require
- * one.
- */
-
-@interface TerminalView : NSImageView
-{
-    NSFont *font;
-    NSImage *image;
-    Terminal *term;
-    Config cfg;
-    NSColor *colours[NALLCOLOURS];
-    float fw, fasc, fdesc, fh;
-}
-- (void)drawStartFinish:(BOOL)start;
-- (void)setColour:(int)n r:(float)r g:(float)g b:(float)b;
-- (void)doText:(wchar_t *)text len:(int)len x:(int)x y:(int)y
-    attr:(unsigned long)attr lattr:(int)lattr;
-@end
-
-@implementation TerminalView
-- (BOOL)isFlipped
-{
-    return YES;
-}
-- (id)initWithTerminal:(Terminal *)aTerm config:(Config)aCfg
-{
-    float w, h;
-
-    self = [self initWithFrame:NSMakeRect(0,0,100,100)];
-
-    term = aTerm;
-    cfg = aCfg;
-
-    /*
-     * Initialise the fonts we're going to use.
-     * 
-     * FIXME: for the moment I'm sticking with exactly one default font.
-     */
-    font = [NSFont userFixedPitchFontOfSize:0];
-
-    /*
-     * Now determine the size of the primary font.
-     * 
-     * FIXME: If we have multiple fonts, we may need to set fasc
-     * and fdesc to the _maximum_ asc and desc out of all the
-     * fonts, _before_ adding them together to get fh.
-     */
-    fw = [font widthOfString:@"A"];
-    fasc = [font ascender];
-    fdesc = -[font descender];
-    fh = fasc + fdesc;
-    fh = (int)fh + (fh > (int)fh);     /* round up, ickily */
-
-    /*
-     * Use this to figure out the size of the terminal view.
-     */
-    w = fw * term->cols;
-    h = fh * term->rows;
-
-    /*
-     * And set our size and subimage.
-     */
-    image = [[NSImage alloc] initWithSize:NSMakeSize(w,h)];
-    [image setFlipped:YES];
-    [self setImage:image];
-    [self setFrame:NSMakeRect(0,0,w,h)];
-
-    term_invalidate(term);
-
-    return self;
-}
-- (void)drawStartFinish:(BOOL)start
-{
-    if (start)
-       [image lockFocus];
-    else
-       [image unlockFocus];
-}
-- (void)doText:(wchar_t *)text len:(int)len x:(int)x y:(int)y
-    attr:(unsigned long)attr lattr:(int)lattr
-{
-    int nfg, nbg, rlen, widefactor;
-    float ox, oy, tw, th;
-    NSDictionary *attrdict;
-
-    /* FIXME: TATTR_COMBINING */
-
-    nfg = ((attr & ATTR_FGMASK) >> ATTR_FGSHIFT);
-    nbg = ((attr & ATTR_BGMASK) >> ATTR_BGSHIFT);
-    if (attr & ATTR_REVERSE) {
-       int t = nfg;
-       nfg = nbg;
-       nbg = t;
-    }
-    if ((cfg.bold_style & 2) && (attr & ATTR_BOLD)) {
-       if (nfg < 16) nfg |= 8;
-       else if (nfg >= 256) nfg |= 1;
-    }
-    if ((cfg.bold_style & 2) && (attr & ATTR_BLINK)) {
-       if (nbg < 16) nbg |= 8;
-       else if (nbg >= 256) nbg |= 1;
-    }
-    if (attr & TATTR_ACTCURS) {
-       nfg = 260;
-       nbg = 261;
-    }
-
-    if (attr & ATTR_WIDE) {
-       widefactor = 2;
-       /* FIXME: what do we actually have to do about wide characters? */
-    } else {
-       widefactor = 1;
-    }
-
-    /* FIXME: ATTR_BOLD if cfg.bold_style & 1 */
-
-    if ((lattr & LATTR_MODE) != LATTR_NORM) {
-       x *= 2;
-       if (x >= term->cols)
-           return;
-       if (x + len*2*widefactor > term->cols)
-           len = (term->cols-x)/2/widefactor;/* trim to LH half */
-       rlen = len * 2;
-    } else
-       rlen = len;
-
-    /* FIXME: how do we actually implement double-{width,height} lattrs? */
-
-    ox = x * fw;
-    oy = y * fh;
-    tw = rlen * widefactor * fw;
-    th = fh;
-
-    /*
-     * Set the clipping rectangle.
-     */
-    [[NSGraphicsContext currentContext] saveGraphicsState];
-    [NSBezierPath clipRect:NSMakeRect(ox, oy, tw, th)];
-
-    attrdict = [NSDictionary dictionaryWithObjectsAndKeys:
-               colours[nfg], NSForegroundColorAttributeName,
-               colours[nbg], NSBackgroundColorAttributeName,
-               font, NSFontAttributeName, nil];
-
-    /*
-     * Create an NSString and draw it.
-     * 
-     * Annoyingly, although our input is wchar_t which is four
-     * bytes wide on OS X and terminal.c supports 32-bit Unicode,
-     * we must convert into the two-byte type `unichar' to store in
-     * NSString, so we lose display capability for extra-BMP stuff
-     * at this point.
-     */
-    {
-       NSString *string;
-       unichar *utext;
-       int i;
-
-       utext = snewn(len, unichar);
-       for (i = 0; i < len; i++)
-           utext[i] = (text[i] >= 0x10000 ? 0xFFFD : text[i]);
-
-       string = [NSString stringWithCharacters:utext length:len];
-       [string drawAtPoint:NSMakePoint(ox, oy) withAttributes:attrdict];
-
-       sfree(utext);
-    }
-
-    /*
-     * Restore the graphics state from before the clipRect: call.
-     */
-    [[NSGraphicsContext currentContext] restoreGraphicsState];
-
-    /*
-     * And flag this area as needing display.
-     */
-    [self setNeedsDisplayInRect:NSMakeRect(ox, oy, tw, th)];
-}
-
-- (void)setColour:(int)n r:(float)r g:(float)g b:(float)b
-{
-    assert(n >= 0 && n < lenof(colours));
-    colours[n] = [[NSColor colorWithDeviceRed:r green:g blue:b alpha:1.0]
-                 retain];
-}
-@end
-
-@implementation SessionWindow
-- (id)initWithConfig:(Config)aCfg
-{
-    NSRect rect = { {0,0}, {0,0} };
-
-    alert_ctx = NULL;
-
-    cfg = aCfg;                               /* structure copy */
-
-    init_ucs(&ucsdata, cfg.line_codepage, cfg.utf8_override,
-            CS_UTF8, cfg.vtmode);
-    term = term_init(&cfg, &ucsdata, self);
-    logctx = log_init(self, &cfg);
-    term_provide_logctx(term, logctx);
-    term_size(term, cfg.height, cfg.width, cfg.savelines);
-
-    termview = [[[TerminalView alloc] initWithTerminal:term config:cfg]
-               autorelease];
-
-    /*
-     * Now work out the size of the window.
-     */
-    rect = [termview frame];
-    rect.origin = NSMakePoint(0,0);
-    rect.size.width += 2 * cfg.window_border;
-    rect.size.height += 2 * cfg.window_border;
-
-    /*
-     * Set up a backend.
-     */
-    back = backend_from_proto(cfg.protocol);
-    if (!back)
-       back = &pty_backend;
-
-    {
-       const char *error;
-       char *realhost = NULL;
-       error = back->init(self, &backhandle, &cfg, cfg.host, cfg.port,
-                          &realhost, cfg.tcp_nodelay, cfg.tcp_keepalives);
-       if (error) {
-           fatalbox("%s\n", error);   /* FIXME: connection_fatal at worst */
-       }
-
-       if (realhost)
-           sfree(realhost);           /* FIXME: do something with this */
-    }
-    back->provide_logctx(backhandle, logctx);
-
-    /*
-     * Create a line discipline. (This must be done after creating
-     * the terminal _and_ the backend, since it needs to be passed
-     * pointers to both.)
-     */
-    ldisc = ldisc_create(&cfg, term, back, backhandle, self);
-
-    /*
-     * FIXME: Set up a scrollbar.
-     */
-
-    self = [super initWithContentRect:rect
-           styleMask:(NSTitledWindowMask | NSMiniaturizableWindowMask |
-                      NSClosableWindowMask)
-           backing:NSBackingStoreBuffered
-           defer:YES];
-    [self setTitle:@"PuTTY"];
-
-    [self setIgnoresMouseEvents:NO];
-
-    /*
-     * Put the terminal view in the window.
-     */
-    rect = [termview frame];
-    rect.origin = NSMakePoint(cfg.window_border, cfg.window_border);
-    [termview setFrame:rect];
-    [[self contentView] addSubview:termview];
-
-    /*
-     * Set up the colour palette.
-     */
-    palette_reset(self);
-
-    /*
-     * FIXME: Only the _first_ document window should be centred.
-     * The subsequent ones should appear down and to the right of
-     * it, probably using the cascade function provided by Cocoa.
-     * Also we're apparently required by the HIG to remember and
-     * reuse previous positions of windows, although I'm not sure
-     * how that works if the user opens more than one of the same
-     * session type.
-     */
-    [self center];                    /* :-) */
-
-    exited = FALSE;
-
-    return self;
-}
-
-- (void)dealloc
-{
-    /*
-     * FIXME: Here we must deallocate all sorts of stuff: the
-     * terminal, the backend, the ldisc, the logctx, you name it.
-     * Do so.
-     */
-    sfree(alert_ctx);
-    if (back)
-       back->free(backhandle);
-    if (ldisc)
-       ldisc_free(ldisc);
-    /* ldisc must be freed before term, since ldisc_free expects term
-     * still to be around. */
-    if (logctx)
-       log_free(logctx);
-    if (term)
-       term_free(term);
-    [super dealloc];
-}
-
-- (void)drawStartFinish:(BOOL)start
-{
-    [termview drawStartFinish:start];
-}
-
-- (void)setColour:(int)n r:(float)r g:(float)g b:(float)b
-{
-    [termview setColour:n r:r g:g b:b];
-}
-
-- (void)doText:(wchar_t *)text len:(int)len x:(int)x y:(int)y
-    attr:(unsigned long)attr lattr:(int)lattr
-{
-    /* Pass this straight on to the TerminalView. */
-    [termview doText:text len:len x:x y:y attr:attr lattr:lattr];
-}
-
-- (Config *)cfg
-{
-    return &cfg;
-}
-
-- (void)keyDown:(NSEvent *)ev
-{
-    NSString *s = [ev characters];
-    int i;
-    int n = [s length], c = [s characterAtIndex:0], m = [ev modifierFlags];
-    int cm = [[ev charactersIgnoringModifiers] characterAtIndex:0];
-    wchar_t output[32];
-    char coutput[32];
-    int use_coutput = FALSE, special = FALSE, start, end;
-
-//printf("n=%d c=U+%04x cm=U+%04x m=%08x\n", n, c, cm, m);
-
-    /*
-     * FIXME: Alt+numberpad codes.
-     */
-
-    /*
-     * Shift and Ctrl with PageUp/PageDown for scrollback.
-     */
-    if (n == 1 && c == NSPageUpFunctionKey && (m & NSShiftKeyMask)) {
-       term_scroll(term, 0, -term->rows/2);
-       return;
-    }
-    if (n == 1 && c == NSPageUpFunctionKey && (m & NSControlKeyMask)) {
-       term_scroll(term, 0, -1);
-       return;
-    }
-    if (n == 1 && c == NSPageDownFunctionKey && (m & NSShiftKeyMask)) {
-       term_scroll(term, 0, +term->rows/2);
-       return;
-    }
-    if (n == 1 && c == NSPageDownFunctionKey && (m & NSControlKeyMask)) {
-       term_scroll(term, 0, +1);
-       return;
-    }
-
-    /*
-     * FIXME: Shift-Ins for paste? Or is that not Maccy enough?
-     */
-
-    /*
-     * FIXME: Alt (Option? Command?) prefix in general.
-     * 
-     * (Note that Alt-Shift-thing will work just by looking at
-     * charactersIgnoringModifiers; but Alt-Ctrl-thing will need
-     * processing properly, and Alt-as-in-Option won't happen at
-     * all. Hmmm.)
-     * 
-     * (Note also that we need to be able to override menu key
-     * equivalents before this is particularly useful.)
-     */
-    start = 1;
-    end = start;
-
-    /*
-     * Ctrl-` is the same as Ctrl-\, unless we already have a
-     * better idea.
-     */
-    if ((m & NSControlKeyMask) && n == 1 && cm == '`' && c == '`') {
-       output[1] = '\x1c';
-       end = 2;
-    }
-
-    /* We handle Return ourselves, because it needs to be flagged as
-     * special to ldisc. */
-    if (n == 1 && c == '\015') {
-       coutput[1] = '\015';
-       use_coutput = TRUE;
-       end = 2;
-       special = TRUE;
-    }
-
-    /* Control-Shift-Space is 160 (ISO8859 nonbreaking space) */
-    if (n == 1 && (m & NSControlKeyMask) && (m & NSShiftKeyMask) &&
-       cm == ' ') {
-       output[1] = '\240';
-       end = 2;
-    }
-
-    /* Control-2, Control-Space and Control-@ are all NUL. */
-    if ((m & NSControlKeyMask) && n == 1 &&
-       (cm == '2' || cm == '@' || cm == ' ') && c == cm) {
-       output[1] = '\0';
-       end = 2;
-    }
-
-    /* We don't let MacOS tell us what Backspace is! We know better. */
-    if (cm == 0x7F && !(m & NSShiftKeyMask)) {
-       coutput[1] = cfg.bksp_is_delete ? '\x7F' : '\x08';
-       end = 2;
-       use_coutput = special = TRUE;
-    }
-    /* For Shift Backspace, do opposite of what is configured. */
-    if (cm == 0x7F && (m & NSShiftKeyMask)) {
-       coutput[1] = cfg.bksp_is_delete ? '\x08' : '\x7F';
-       end = 2;
-       use_coutput = special = TRUE;
-    }
-
-    /* Shift-Tab is ESC [ Z. Oddly, this combination generates ^Y by
-     * default on MacOS! */
-    if (cm == 0x19 && (m & NSShiftKeyMask) && !(m & NSControlKeyMask)) {
-       end = 1;
-       output[end++] = '\033';
-       output[end++] = '[';
-       output[end++] = 'Z';
-    }
-
-    /*
-     * NetHack keypad mode.
-     */
-    if (cfg.nethack_keypad && (m & NSNumericPadKeyMask)) {
-       wchar_t *keys = NULL;
-       switch (cm) {
-         case '1': keys = L"bB"; break;
-         case '2': keys = L"jJ"; break;
-         case '3': keys = L"nN"; break;
-         case '4': keys = L"hH"; break;
-         case '5': keys = L".."; break;
-         case '6': keys = L"lL"; break;
-         case '7': keys = L"yY"; break;
-         case '8': keys = L"kK"; break;
-         case '9': keys = L"uU"; break;
-       }
-       if (keys) {
-           end = 2;
-           if (m & NSShiftKeyMask)
-               output[1] = keys[1];
-           else
-               output[1] = keys[0];
-           goto done;
-       }
-    }
-
-    /*
-     * Application keypad mode.
-     */
-    if (term->app_keypad_keys && !cfg.no_applic_k &&
-       (m & NSNumericPadKeyMask)) {
-       int xkey = 0;
-       switch (cm) {
-         case NSClearLineFunctionKey: xkey = 'P'; break;
-         case '=': xkey = 'Q'; break;
-         case '/': xkey = 'R'; break;
-         case '*': xkey = 'S'; break;
-           /*
-            * FIXME: keypad - and + need to be mapped to ESC O l
-            * and ESC O k, or ESC O l and ESC O m, depending on
-            * xterm function key mode, and I can't remember which
-            * goes where.
-            */
-         case '\003': xkey = 'M'; break;
-         case '0': xkey = 'p'; break;
-         case '1': xkey = 'q'; break;
-         case '2': xkey = 'r'; break;
-         case '3': xkey = 's'; break;
-         case '4': xkey = 't'; break;
-         case '5': xkey = 'u'; break;
-         case '6': xkey = 'v'; break;
-         case '7': xkey = 'w'; break;
-         case '8': xkey = 'x'; break;
-         case '9': xkey = 'y'; break;
-         case '.': xkey = 'n'; break;
-       }
-       if (xkey) {
-           if (term->vt52_mode) {
-               if (xkey >= 'P' && xkey <= 'S') {
-                   output[end++] = '\033';
-                   output[end++] = xkey;
-               } else {
-                   output[end++] = '\033';
-                   output[end++] = '?';
-                   output[end++] = xkey;
-               }
-           } else {
-               output[end++] = '\033';
-               output[end++] = 'O';
-               output[end++] = xkey;
-           }
-           goto done;
-       }
-    }
-
-    /*
-     * Next, all the keys that do tilde codes. (ESC '[' nn '~',
-     * for integer decimal nn.)
-     *
-     * We also deal with the weird ones here. Linux VCs replace F1
-     * to F5 by ESC [ [ A to ESC [ [ E. rxvt doesn't do _that_, but
-     * does replace Home and End (1~ and 4~) by ESC [ H and ESC O w
-     * respectively.
-     */
-    {
-       int code = 0;
-       switch (cm) {
-         case NSF1FunctionKey:
-           code = (m & NSShiftKeyMask ? 23 : 11);
-           break;
-         case NSF2FunctionKey:
-           code = (m & NSShiftKeyMask ? 24 : 12);
-           break;
-         case NSF3FunctionKey:
-           code = (m & NSShiftKeyMask ? 25 : 13);
-           break;
-         case NSF4FunctionKey:
-           code = (m & NSShiftKeyMask ? 26 : 14);
-           break;
-         case NSF5FunctionKey:
-           code = (m & NSShiftKeyMask ? 28 : 15);
-           break;
-         case NSF6FunctionKey:
-           code = (m & NSShiftKeyMask ? 29 : 17);
-           break;
-         case NSF7FunctionKey:
-           code = (m & NSShiftKeyMask ? 31 : 18);
-           break;
-         case NSF8FunctionKey:
-           code = (m & NSShiftKeyMask ? 32 : 19);
-           break;
-         case NSF9FunctionKey:
-           code = (m & NSShiftKeyMask ? 33 : 20);
-           break;
-         case NSF10FunctionKey:
-           code = (m & NSShiftKeyMask ? 34 : 21);
-           break;
-         case NSF11FunctionKey:
-           code = 23;
-           break;
-         case NSF12FunctionKey:
-           code = 24;
-           break;
-         case NSF13FunctionKey:
-           code = 25;
-           break;
-         case NSF14FunctionKey:
-           code = 26;
-           break;
-         case NSF15FunctionKey:
-           code = 28;
-           break;
-         case NSF16FunctionKey:
-           code = 29;
-           break;
-         case NSF17FunctionKey:
-           code = 31;
-           break;
-         case NSF18FunctionKey:
-           code = 32;
-           break;
-         case NSF19FunctionKey:
-           code = 33;
-           break;
-         case NSF20FunctionKey:
-           code = 34;
-           break;
-       }
-       if (!(m & NSControlKeyMask)) switch (cm) {
-         case NSHomeFunctionKey:
-           code = 1;
-           break;
-#ifdef FIXME
-         case GDK_Insert: case GDK_KP_Insert:
-           code = 2;
-           break;
-#endif
-         case NSDeleteFunctionKey:
-           code = 3;
-           break;
-         case NSEndFunctionKey:
-           code = 4;
-           break;
-         case NSPageUpFunctionKey:
-           code = 5;
-           break;
-         case NSPageDownFunctionKey:
-           code = 6;
-           break;
-       }
-       /* Reorder edit keys to physical order */
-       if (cfg.funky_type == FUNKY_VT400 && code <= 6)
-           code = "\0\2\1\4\5\3\6"[code];
-
-       if (term->vt52_mode && code > 0 && code <= 6) {
-           output[end++] = '\033';
-           output[end++] = " HLMEIG"[code];
-           goto done;
-       }
-
-       if (cfg.funky_type == FUNKY_SCO &&     /* SCO function keys */
-           code >= 11 && code <= 34) {
-           char codes[] = "MNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@[\\]^_`{";
-           int index = 0;
-           switch (cm) {
-             case NSF1FunctionKey: index = 0; break;
-             case NSF2FunctionKey: index = 1; break;
-             case NSF3FunctionKey: index = 2; break;
-             case NSF4FunctionKey: index = 3; break;
-             case NSF5FunctionKey: index = 4; break;
-             case NSF6FunctionKey: index = 5; break;
-             case NSF7FunctionKey: index = 6; break;
-             case NSF8FunctionKey: index = 7; break;
-             case NSF9FunctionKey: index = 8; break;
-             case NSF10FunctionKey: index = 9; break;
-             case NSF11FunctionKey: index = 10; break;
-             case NSF12FunctionKey: index = 11; break;
-           }
-           if (m & NSShiftKeyMask) index += 12;
-           if (m & NSControlKeyMask) index += 24;
-           output[end++] = '\033';
-           output[end++] = '[';
-           output[end++] = codes[index];
-           goto done;
-       }
-       if (cfg.funky_type == FUNKY_SCO &&     /* SCO small keypad */
-           code >= 1 && code <= 6) {
-           char codes[] = "HL.FIG";
-           if (code == 3) {
-               output[1] = '\x7F';
-               end = 2;
-           } else {
-               output[end++] = '\033';
-               output[end++] = '[';
-               output[end++] = codes[code-1];
-           }
-           goto done;
-       }
-       if ((term->vt52_mode || cfg.funky_type == FUNKY_VT100P) &&
-           code >= 11 && code <= 24) {
-           int offt = 0;
-           if (code > 15)
-               offt++;
-           if (code > 21)
-               offt++;
-           if (term->vt52_mode) {
-               output[end++] = '\033';
-               output[end++] = code + 'P' - 11 - offt;
-           } else {
-               output[end++] = '\033';
-               output[end++] = 'O';
-               output[end++] = code + 'P' - 11 - offt;
-           }
-           goto done;
-       }
-       if (cfg.funky_type == FUNKY_LINUX && code >= 11 && code <= 15) {
-           output[end++] = '\033';
-           output[end++] = '[';
-           output[end++] = '[';        
-           output[end++] = code + 'A' - 11;
-           goto done;
-       }
-       if (cfg.funky_type == FUNKY_XTERM && code >= 11 && code <= 14) {
-           if (term->vt52_mode) {
-               output[end++] = '\033';
-               output[end++] = code + 'P' - 11;
-           } else {
-               output[end++] = '\033';
-               output[end++] = 'O';
-               output[end++] = code + 'P' - 11;
-           }
-           goto done;
-       }
-       if (cfg.rxvt_homeend && (code == 1 || code == 4)) {
-           if (code == 1) {
-               output[end++] = '\033';
-               output[end++] = '[';
-               output[end++] = 'H';
-           } else {
-               output[end++] = '\033';
-               output[end++] = 'O';
-               output[end++] = 'w';
-           }
-           goto done;
-       }
-       if (code) {
-           char buf[20];
-           sprintf(buf, "\x1B[%d~", code);
-           for (i = 0; buf[i]; i++)
-               output[end++] = buf[i];
-           goto done;
-       }
-    }
-
-    /*
-     * Cursor keys. (This includes the numberpad cursor keys,
-     * if we haven't already done them due to app keypad mode.)
-     */
-    {
-       int xkey = 0;
-       switch (cm) {
-         case NSUpArrowFunctionKey: xkey = 'A'; break;
-         case NSDownArrowFunctionKey: xkey = 'B'; break;
-         case NSRightArrowFunctionKey: xkey = 'C'; break;
-         case NSLeftArrowFunctionKey: xkey = 'D'; break;
-       }
-       if (xkey) {
-           end += format_arrow_key(output+end, term, xkey,
-                                   m & NSControlKeyMask);
-           goto done;
-       }
-    }
-
-    done:
-
-    /*
-     * Failing everything else, send the exact Unicode we got from
-     * OS X.
-     */
-    if (end == start) {
-       if (n > lenof(output)-start)
-           n = lenof(output)-start;   /* _shouldn't_ happen! */
-       for (i = 0; i < n; i++) {
-           output[i+start] = [s characterAtIndex:i];
-       }
-       end = n+start;
-    }
-
-    if (use_coutput) {
-       assert(special);
-       assert(end < lenof(coutput));
-       coutput[end] = '\0';
-       ldisc_send(ldisc, coutput+start, -2, TRUE);
-    } else {
-       luni_send(ldisc, output+start, end-start, TRUE);
-    }
-}
-
-- (int)fromBackend:(const char *)data len:(int)len isStderr:(int)is_stderr
-{
-    return term_data(term, is_stderr, data, len);
-}
-
-- (int)fromBackendUntrusted:(const char *)data len:(int)len
-{
-    return term_data_untrusted(term, data, len);
-}
-
-- (void)startAlert:(NSAlert *)alert
-    withCallback:(void (*)(void *, int))callback andCtx:(void *)ctx
-{
-    if (alert_ctx || alert_qhead) {
-       /*
-        * Queue this alert to be shown later.
-        */
-       struct alert_queue *qitem = snew(struct alert_queue);
-       qitem->next = NULL;
-       qitem->alert = alert;
-       qitem->callback = callback;
-       qitem->ctx = ctx;
-       if (alert_qtail)
-           alert_qtail->next = qitem;
-       else
-           alert_qhead = qitem;
-       alert_qtail = qitem;
-    } else {
-       alert_callback = callback;
-       alert_ctx = ctx;               /* NB this is assumed to need freeing! */
-       [alert beginSheetModalForWindow:self modalDelegate:self
-        didEndSelector:@selector(alertSheetDidEnd:returnCode:contextInfo:)
-        contextInfo:NULL];
-    }
-}
-
-- (void)alertSheetDidEnd:(NSAlert *)alert returnCode:(int)returnCode
-    contextInfo:(void *)contextInfo
-{
-    [self performSelectorOnMainThread:
-     @selector(alertSheetDidFinishEnding:)
-     withObject:[NSNumber numberWithInt:returnCode]
-     waitUntilDone:NO];
-}
-
-- (void)alertSheetDidFinishEnding:(id)object
-{
-    int returnCode = [object intValue];
-
-    alert_callback(alert_ctx, returnCode);   /* transfers ownership of ctx */
-
-    /*
-     * If there's an alert in our queue (either already or because
-     * the callback just queued it), start it.
-     */
-    if (alert_qhead) {
-       struct alert_queue *qnext;
-
-       alert_callback = alert_qhead->callback;
-       alert_ctx = alert_qhead->ctx;
-       [alert_qhead->alert beginSheetModalForWindow:self modalDelegate:self
-        didEndSelector:@selector(alertSheetDidEnd:returnCode:contextInfo:)
-        contextInfo:NULL];
-
-       qnext = alert_qhead->next;
-       sfree(alert_qhead);
-       alert_qhead = qnext;
-       if (!qnext)
-           alert_qtail = NULL;
-    } else {
-       alert_ctx = NULL;
-    }
-}
-
-- (void)notifyRemoteExit
-{
-    int exitcode;
-
-    if (!exited && (exitcode = back->exitcode(backhandle)) >= 0)
-       [self endSession:(exitcode == 0)];
-}
-
-- (void)endSession:(int)clean
-{
-    exited = TRUE;
-    if (ldisc) {
-       ldisc_free(ldisc);
-       ldisc = NULL;
-    }
-    if (back) {
-       back->free(backhandle);
-       backhandle = NULL;
-       back = NULL;
-       //FIXME: update specials menu;
-    }
-    if (cfg.close_on_exit == FORCE_ON ||
-       (cfg.close_on_exit == AUTO && clean))
-       [self close];
-    // FIXME: else show restart menu item
-}
-
-- (Terminal *)term
-{
-    return term;
-}
-
-@end
-
-int from_backend(void *frontend, int is_stderr, const char *data, int len)
-{
-    SessionWindow *win = (SessionWindow *)frontend;
-    return [win fromBackend:data len:len isStderr:is_stderr];
-}
-
-int from_backend_untrusted(void *frontend, const char *data, int len)
-{
-    SessionWindow *win = (SessionWindow *)frontend;
-    return [win fromBackendUntrusted:data len:len];
-}
-
-int get_userpass_input(prompts_t *p, const unsigned char *in, int inlen)
-{
-    SessionWindow *win = (SessionWindow *)p->frontend;
-    Terminal *term = [win term];
-    return term_get_userpass_input(term, p, in, inlen);
-}
-
-void frontend_keypress(void *handle)
-{
-    /* FIXME */
-}
-
-void notify_remote_exit(void *frontend)
-{
-    SessionWindow *win = (SessionWindow *)frontend;
-
-    [win notifyRemoteExit];
-}
-
-void frontend_echoedit_update(void *frontend, int echo, int edit)
-{
-    //SessionWindow *win = (SessionWindow *)frontend;
-    /*
-     * In a GUI front end, this need do nothing.
-     */
-}
-
-char *get_ttymode(void *frontend, const char *mode)
-{
-    SessionWindow *win = (SessionWindow *)frontend;
-    Terminal *term = [win term];
-    return term_get_ttymode(term, mode);
-}
-
-void update_specials_menu(void *frontend)
-{
-    //SessionWindow *win = (SessionWindow *)frontend;
-    /* FIXME */
-}
-
-/*
- * This is still called when mode==BELL_VISUAL, even though the
- * visual bell is handled entirely within terminal.c, because we
- * may want to perform additional actions on any kind of bell (for
- * example, taskbar flashing in Windows).
- */
-void do_beep(void *frontend, int mode)
-{
-    //SessionWindow *win = (SessionWindow *)frontend;
-    if (mode != BELL_VISUAL)
-       NSBeep();
-}
-
-int char_width(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;
-}
-
-void palette_set(void *frontend, int n, int r, int g, int b)
-{
-    SessionWindow *win = (SessionWindow *)frontend;
-
-    if (n >= 16)
-       n += 256 - 16;
-    if (n >= NALLCOLOURS)
-       return;
-    [win setColour:n r:r/255.0 g:g/255.0 b:b/255.0];
-
-    /*
-     * FIXME: do we need an OS X equivalent of set_window_background?
-     */
-}
-
-void palette_reset(void *frontend)
-{
-    SessionWindow *win = (SessionWindow *)frontend;
-    Config *cfg = [win cfg];
-
-    /* This maps colour indices in cfg to those used in colours[]. */
-    static const int ww[] = {
-       256, 257, 258, 259, 260, 261,
-       0, 8, 1, 9, 2, 10, 3, 11,
-       4, 12, 5, 13, 6, 14, 7, 15
-    };
-
-    int i;
-
-    for (i = 0; i < NCFGCOLOURS; i++) {
-       [win setColour:ww[i] r:cfg->colours[i][0]/255.0
-        g:cfg->colours[i][1]/255.0 b:cfg->colours[i][2]/255.0];
-    }
-
-    for (i = 0; i < NEXTCOLOURS; i++) {
-       if (i < 216) {
-           int r = i / 36, g = (i / 6) % 6, b = i % 6;
-           r = r ? r*40+55 : 0; g = g ? b*40+55 : 0; b = b ? b*40+55 : 0;
-           [win setColour:i+16 r:r/255.0 g:g/255.0 b:b/255.0];
-       } else {
-           int shade = i - 216;
-           float fshade = (shade * 10 + 8) / 255.0;
-           [win setColour:i+16 r:fshade g:fshade b:fshade];
-       }
-    }
-
-    /*
-     * FIXME: do we need an OS X equivalent of set_window_background?
-     */
-}
-
-Context get_ctx(void *frontend)
-{
-    SessionWindow *win = (SessionWindow *)frontend;
-
-    /*
-     * Lock the drawing focus on the image inside the TerminalView.
-     */
-    [win drawStartFinish:YES];
-
-    [[NSGraphicsContext currentContext] setShouldAntialias:YES];
-
-    /*
-     * Cocoa drawing functions don't take a graphics context: that
-     * parameter is implicit. Therefore, we'll use the frontend
-     * handle itself as the context, on the grounds that it's as
-     * good a thing to use as any.
-     */
-    return frontend;
-}
-
-void free_ctx(Context ctx)
-{
-    SessionWindow *win = (SessionWindow *)ctx;
-
-    [win drawStartFinish:NO];
-}
-
-void do_text(Context ctx, int x, int y, wchar_t *text, int len,
-            unsigned long attr, int lattr)
-{
-    SessionWindow *win = (SessionWindow *)ctx;
-
-    [win doText:text len:len x:x y:y attr:attr lattr:lattr];
-}
-
-void do_cursor(Context ctx, int x, int y, wchar_t *text, int len,
-              unsigned long attr, int lattr)
-{
-    SessionWindow *win = (SessionWindow *)ctx;
-    Config *cfg = [win cfg];
-    int active, passive;
-
-    if (attr & TATTR_PASCURS) {
-       attr &= ~TATTR_PASCURS;
-       passive = 1;
-    } else
-       passive = 0;
-    if ((attr & TATTR_ACTCURS) && cfg->cursor_type != 0) {
-       attr &= ~TATTR_ACTCURS;
-        active = 1;
-    } else
-        active = 0;
-
-    [win doText:text len:len x:x y:y attr:attr lattr:lattr];
-
-    /*
-     * FIXME: now draw the various cursor types (both passive and
-     * active underlines and vertical lines, plus passive blocks).
-     */
-}
-
-/*
- * Minimise or restore the window in response to a server-side
- * request.
- */
-void set_iconic(void *frontend, int iconic)
-{
-    //SessionWindow *win = (SessionWindow *)frontend;
-    /* FIXME */
-}
-
-/*
- * Move the window in response to a server-side request.
- */
-void move_window(void *frontend, int x, int y)
-{
-    //SessionWindow *win = (SessionWindow *)frontend; 
-    /* FIXME */
-}
-
-/*
- * Move the window to the top or bottom of the z-order in response
- * to a server-side request.
- */
-void set_zorder(void *frontend, int top)
-{
-    //SessionWindow *win = (SessionWindow *)frontend;
-    /* FIXME */
-}
-
-/*
- * Refresh the window in response to a server-side request.
- */
-void refresh_window(void *frontend)
-{
-    //SessionWindow *win = (SessionWindow *)frontend;
-    /* FIXME */
-}
-
-/*
- * Maximise or restore the window in response to a server-side
- * request.
- */
-void set_zoomed(void *frontend, int zoomed)
-{
-    //SessionWindow *win = (SessionWindow *)frontend;
-    /* FIXME */
-}
-
-/*
- * Report whether the window is iconic, for terminal reports.
- */
-int is_iconic(void *frontend)
-{
-    //SessionWindow *win = (SessionWindow *)frontend;
-    return NO;                                /* FIXME */
-}
-
-/*
- * Report the window's position, for terminal reports.
- */
-void get_window_pos(void *frontend, int *x, int *y)
-{
-    //SessionWindow *win = (SessionWindow *)frontend;
-    /* FIXME */
-}
-
-/*
- * Report the window's pixel size, for terminal reports.
- */
-void get_window_pixels(void *frontend, int *x, int *y)
-{
-    //SessionWindow *win = (SessionWindow *)frontend;
-    /* FIXME */
-}
-
-/*
- * Return the window or icon title.
- */
-char *get_window_title(void *frontend, int icon)
-{
-    //SessionWindow *win = (SessionWindow *)frontend;
-    return NULL; /* FIXME */
-}
-
-void set_title(void *frontend, char *title)
-{
-    //SessionWindow *win = (SessionWindow *)frontend;
-    /* FIXME */
-}
-
-void set_icon(void *frontend, char *title)
-{
-    //SessionWindow *win = (SessionWindow *)frontend;
-    /* FIXME */
-}
-
-void set_sbar(void *frontend, int total, int start, int page)
-{
-    //SessionWindow *win = (SessionWindow *)frontend;
-    /* FIXME */
-}
-
-void get_clip(void *frontend, wchar_t ** p, int *len)
-{
-    //SessionWindow *win = (SessionWindow *)frontend;
-    /* FIXME */
-}
-
-void write_clip(void *frontend, wchar_t *data, int *attr, int len, int must_deselect)
-{
-    //SessionWindow *win = (SessionWindow *)frontend;
-    /* FIXME */
-}
-
-void request_paste(void *frontend)
-{
-    //SessionWindow *win = (SessionWindow *)frontend;
-    /* FIXME */
-}
-
-void set_raw_mouse_mode(void *frontend, int activate)
-{
-    //SessionWindow *win = (SessionWindow *)frontend;
-    /* FIXME */
-}
-
-void request_resize(void *frontend, int w, int h)
-{
-    //SessionWindow *win = (SessionWindow *)frontend;
-    /* FIXME */
-}
-
-void sys_cursor(void *frontend, int x, int y)
-{
-    //SessionWindow *win = (SessionWindow *)frontend;
-    /*
-     * This is probably meaningless under OS X. FIXME: find out for
-     * sure.
-     */
-}
-
-void logevent(void *frontend, const char *string)
-{
-    //SessionWindow *win = (SessionWindow *)frontend;
-    /* FIXME */
-printf("logevent: %s\n", string);
-}
-
-int font_dimension(void *frontend, int which)/* 0 for width, 1 for height */
-{
-    //SessionWindow *win = (SessionWindow *)frontend;
-    return 1; /* FIXME */
-}
-
-void set_busy_status(void *frontend, int status)
-{
-    /*
-     * We need do nothing here: the OS X `application is busy'
-     * beachball pointer appears _automatically_ when the
-     * application isn't responding to GUI messages.
-     */
-}
index 724bf9b8d21ae9b8a147395604484302856081ff..27916d276ae946c048328a754a580081c94bc37f 100644 (file)
--- a/puttyps.h
+++ b/puttyps.h
@@ -9,10 +9,6 @@
 
 #include "winstuff.h"
 
-#elif defined(MACOSX)
-
-#include "osx.h"
-
 #else
 
 #include "unix.h"