Change the term_mouse interface a little so that it gets passed
[u/mdw/putty] / mac / macterm.c
index c91a734..61dc4b4 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: macterm.c,v 1.37 2003/01/09 22:45:48 ben Exp $ */
+/* $Id: macterm.c,v 1.54 2003/01/25 16:16:44 ben Exp $ */
 /*
  * Copyright (c) 1999 Simon Tatham
  * Copyright (c) 1999, 2002 Ben Harris
@@ -33,6 +33,7 @@
 #include <MacTypes.h>
 #include <Controls.h>
 #include <ControlDefinitions.h>
+#include <FixMath.h>
 #include <Fonts.h>
 #include <Gestalt.h>
 #include <LowMem.h>
@@ -46,9 +47,7 @@
 #include <Scrap.h>
 #include <Script.h>
 #include <Sound.h>
-#include <StandardFile.h>
 #include <TextCommon.h>
-#include <Threads.h>
 #include <ToolUtils.h>
 #include <UnicodeConverter.h>
 
@@ -62,7 +61,6 @@
 #include "putty.h"
 #include "charset.h"
 #include "mac.h"
-#include "storage.h"
 #include "terminal.h"
 
 #define NCOLOURS (lenof(((Config *)0)->colours))
@@ -109,52 +107,12 @@ static RoutineDescriptor do_text_for_device_upp =
 #define do_text_for_device_upp do_text_for_device
 #endif /* not TARGET_RT_MAC_CFM */
 
-static void inbuf_putc(Session *s, int c) {
-    char ch = c;
-
-    from_backend(s->term, 0, &ch, 1);
-}
-
-static void inbuf_putstr(Session *s, const char *c) {
-
-    from_backend(s->term, 0, (char *)c, strlen(c));
-}
-
-static void display_resource(Session *s, unsigned long type, short id) {
-    Handle h;
-    int len;
-    char *t;
-
-    h = GetResource(type, id);
-    if (h == NULL)
-       fatalbox("Can't get test resource");
-    len = GetResourceSizeOnDisk(h);
-    DetachResource(h);
-    HNoPurge(h);
-    HLock(h);
-    t = *h;
-    from_backend(s->term, 0, t, len);
-    term_out(s->term);
-    DisposeHandle(h);
-}
-       
-void mac_opensession(void) {
-    Session *s;
-    StandardFileReply sfr;
-    static const OSType sftypes[] = { 'Sess', 0, 0, 0 };
-    void *sesshandle;
+void mac_startsession(Session *s)
+{
+    char *errmsg;
     int i;
 
-    s = smalloc(sizeof(*s));
-    memset(s, 0, sizeof(*s));
-
-    StandardGetFile(NULL, 1, sftypes, &sfr);
-    if (!sfr.sfGood) goto fail;
-
-    sesshandle = open_settings_r_fsp(&sfr.sfFile);
-    if (sesshandle == NULL) goto fail;
-    load_open_settings(sesshandle, TRUE, &s->cfg);
-    close_settings_r(sesshandle);
+    init_ucs(s);
 
     /*
      * Select protocol. This is farmed out into a table in a
@@ -166,22 +124,8 @@ void mac_opensession(void) {
            s->back = backends[i].backend;
            break;
        }
-    if (s->back == NULL) {
+    if (s->back == NULL)
        fatalbox("Unsupported protocol number found");
-    }
-    mac_startsession(s);
-    return;
-
-  fail:
-    sfree(s);
-    return;
-}
-
-void mac_startsession(Session *s)
-{
-    UInt32 starttime;
-    char msg[128];
-    char *errmsg;
 
     /* XXX: Own storage management? */
     if (HAVE_COLOR_QD())
@@ -190,7 +134,7 @@ void mac_startsession(Session *s)
        s->window = GetNewWindow(wTerminal, NULL, (WindowPtr)-1);
     SetWRefCon(s->window, (long)s);
     s->scrollbar = GetNewControl(cVScroll, s->window);
-    s->term = term_init(&s->cfg, s);
+    s->term = term_init(&s->cfg, &s->ucsdata, s);
 
     mac_initfont(s);
     mac_initpalette(s);
@@ -200,14 +144,15 @@ void mac_startsession(Session *s)
        ActivatePalette(s->window);
     }
 
-    s->logctx = log_init(s);
+    s->logctx = log_init(s, &s->cfg);
     term_provide_logctx(s->term, s->logctx);
 
-    errmsg = s->back->init(s->term, &s->backhandle, s->cfg.host, s->cfg.port,
-                 &s->realhost, s->cfg.tcp_nodelay);
+    errmsg = s->back->init(s->term, &s->backhandle, &s->cfg, s->cfg.host,
+                          s->cfg.port, &s->realhost, s->cfg.tcp_nodelay);
     if (errmsg != NULL)
-       inbuf_putstr(s, errmsg);
+       fatalbox("%s", errmsg);
     s->back->provide_logctx(s->backhandle, s->logctx);
+    set_title(s, s->realhost);
 
     term_provide_resize_fn(s->term, s->back->size, s->backhandle);
 
@@ -218,17 +163,48 @@ void mac_startsession(Session *s)
     ldisc_send(s->ldisc, NULL, 0, 0);/* cause ldisc to notice changes */
 
     ShowWindow(s->window);
-    starttime = TickCount();
-    display_resource(s, 'pTST', 128);
-    sprintf(msg, "Elapsed ticks: %d\015\012", TickCount() - starttime);
-    inbuf_putstr(s, msg);
-    term_out(s->term);
     s->next = sesslist;
-    s->prev = s->next->prev;
-    s->next->prev = &s->next;
+    s->prev = &sesslist;
+    if (s->next != NULL)
+       s->next->prev = &s->next;
     sesslist = s;
 }
 
+/*
+ * Try to work out a horizontal scaling factor for the current font
+ * that will give a chracter width of wantwidth.  Return it in numer
+ * and denom (suitable for passing to StdText()).
+ */
+static void mac_workoutfontscale(Session *s, int wantwidth,
+                                Point *numerp, Point *denomp)
+{
+    Point numer, denom, tmpnumer, tmpdenom;
+    int gotwidth, i;
+    const char text = 'W';
+    FontInfo fi;
+
+    numer.v = denom.v = 1; /* always */
+    numer.h = denom.h = 1;
+    for (i = 0; i < 3; i++) {
+       tmpnumer = numer;
+       tmpdenom = denom;
+       if (s->window->grafProcs != NULL)
+           gotwidth = InvokeQDTxMeasUPP(1, &text, &tmpnumer, &tmpdenom, &fi,
+                                        s->window->grafProcs->txMeasProc);
+       else
+           gotwidth = StdTxMeas(1, &text, &tmpnumer, &tmpdenom, &fi);
+       /* The result of StdTxMeas must be scaled by the factors it returns. */
+       gotwidth = FixRound(FixMul(gotwidth << 16,
+                                  FixRatio(tmpnumer.h, tmpdenom.h)));
+       if (gotwidth == wantwidth)
+           break;
+       numer.h *= wantwidth;
+       denom.h *= gotwidth;
+    }
+    *numerp = numer;
+    *denomp = denom;
+}
+
 static UnicodeToTextFallbackUPP uni_to_font_fallback_upp;
 
 static void mac_initfont(Session *s) {
@@ -238,7 +214,7 @@ static void mac_initfont(Session *s) {
     OptionBits fbflags;
 
     SetPort(s->window);
-    macfont[0] = sprintf((char *)&macfont[1], "%s", s->cfg.font);
+    c2pstrcpy(macfont, s->cfg.font);
     GetFNum(macfont, &s->fontnum);
     TextFont(s->fontnum);
     TextFace(s->cfg.fontisbold ? bold : 0);
@@ -248,6 +224,14 @@ static void mac_initfont(Session *s) {
     s->font_ascent = fi.ascent;
     s->font_leading = fi.leading;
     s->font_height = s->font_ascent + fi.descent + s->font_leading;
+    mac_workoutfontscale(s, s->font_width,
+                        &s->font_stdnumer, &s->font_stddenom);
+    mac_workoutfontscale(s, s->font_width * 2,
+                        &s->font_widenumer, &s->font_widedenom);
+    TextSize(s->cfg.fontheight * 2);
+    mac_workoutfontscale(s, s->font_width * 2,
+                        &s->font_bignumer, &s->font_bigdenom);
+    TextSize(s->cfg.fontheight);
     if (!s->cfg.bold_colour) {
        TextFace(bold);
        s->font_boldadjust = s->font_width - CharWidth('W');
@@ -431,6 +415,10 @@ void mac_adjusttermmenus(WindowPtr window) {
     long offset;
 
     s = (Session *)GetWRefCon(window);
+    menu = GetMenuHandle(mFile);
+    DisableItem(menu, iSave); /* XXX enable if modified */
+    EnableItem(menu, iSaveAs);
+    EnableItem(menu, iDuplicate);
     menu = GetMenuHandle(mEdit);
     EnableItem(menu, 0);
     DisableItem(menu, iUndo);
@@ -514,8 +502,8 @@ static void text_click(Session *s, EventRecord *event) {
                   lastact == MA_3CLK ? MA_CLICK : MA_NOTHING);
     else
        lastact = MA_CLICK;
-    /* Fake right button with shift key */
-    term_mouse(s->term, event->modifiers & shiftKey ? MBT_RIGHT : MBT_LEFT,
+    term_mouse(s->term, MBT_LEFT,
+              event->modifiers & shiftKey ? MBT_EXTEND : MBT_SELECT,
               lastact, col, row, event->modifiers & shiftKey,
               event->modifiers & controlKey, event->modifiers & optionKey);
     lastsess = s;
@@ -525,8 +513,8 @@ static void text_click(Session *s, EventRecord *event) {
        GetMouse(&localwhere);
        col = PTOCC(localwhere.h);
        row = PTOCR(localwhere.v);
-       term_mouse(s->term,
-                  event->modifiers & shiftKey ? MBT_RIGHT : MBT_LEFT,
+       term_mouse(s->term, MBT_LEFT, 
+                  event->modifiers & shiftKey ? MBT_EXTEND : MBT_SELECT,
                   MA_DRAG, col, row, event->modifiers & shiftKey,
                   event->modifiers & controlKey,
                   event->modifiers & optionKey);
@@ -535,25 +523,13 @@ static void text_click(Session *s, EventRecord *event) {
        else if (row < 0)
            term_scroll(s->term, 0, row);
     }
-    term_mouse(s->term, event->modifiers & shiftKey ? MBT_RIGHT : MBT_LEFT,
+    term_mouse(s->term, MBT_LEFT,
+              event->modifiers & shiftKey ? MBT_EXTEND : MBT_SELECT,
               MA_RELEASE, col, row, event->modifiers & shiftKey,
               event->modifiers & controlKey, event->modifiers & optionKey);
     lastwhen = TickCount();
 }
 
-Mouse_Button translate_button(void *frontend, Mouse_Button button)
-{
-
-    switch (button) {
-      case MBT_LEFT:
-       return MBT_SELECT;
-      case MBT_RIGHT:
-       return MBT_EXTEND;
-      default:
-       return 0;
-    }
-}
-
 void write_clip(void *cookie, wchar_t *data, int len, int must_deselect) {
     
     /*
@@ -907,6 +883,25 @@ static pascal void mac_growtermdraghook(void)
     SetPort(portsave);
 }
 
+void mac_closeterm(WindowPtr window)
+{
+    Session *s = (Session *)GetWRefCon(window);
+
+    /* XXX warn on close */
+    HideWindow(s->window);
+    *s->prev = s->next;
+    s->next->prev = s->prev;
+    ldisc_free(s->ldisc);
+    s->back->free(s->backhandle);
+    log_free(s->logctx);
+    if (s->uni_to_font != NULL)
+       DisposeUnicodeToTextInfo(&s->uni_to_font);
+    term_free(s->term);
+    DisposeWindow(s->window);
+    DisposePalette(s->palette);
+    sfree(s);
+}
+
 void mac_activateterm(WindowPtr window, Boolean active) {
     Session *s;
 
@@ -992,23 +987,29 @@ void do_text(Context ctx, int x, int y, char *text, int len,
     Session *s = ctx;
     int style = 0;
     struct do_text_args a;
-    RgnHandle textrgn;
+    RgnHandle textrgn, saveclip;
     char mactextbuf[1024];
     UniChar unitextbuf[1024];
     wchar_t *unitextptr;
-    int i;
+    int i, fontwidth;
     ByteCount iread, olen;
     OSStatus err;
 
     assert(len <= 1024);
 
     SetPort(s->window);
-    
+
+    fontwidth = s->font_width;
+    if ((lattr & LATTR_MODE) != LATTR_NORM)
+       fontwidth *= 2;
+
     /* First check this text is relevant */
     a.textrect.top = y * s->font_height;
     a.textrect.bottom = (y + 1) * s->font_height;
-    a.textrect.left = x * s->font_width;
-    a.textrect.right = (x + len) * s->font_width;
+    a.textrect.left = x * fontwidth;
+    a.textrect.right = (x + len) * fontwidth;
+    if (a.textrect.right > s->term->cols * s->font_width)
+       a.textrect.right = s->term->cols * s->font_width;
     if (!RectInRgn(&a.textrect, s->window->visRgn))
        return;
 
@@ -1036,7 +1037,24 @@ void do_text(Context ctx, int x, int y, char *text, int len,
     a.len = olen;
     a.attr = attr;
     a.lattr = lattr;
-    a.numer.h = a.numer.v = a.denom.h = a.denom.v = 1;
+    switch (lattr & LATTR_MODE) {
+      case LATTR_NORM:
+       TextSize(s->cfg.fontheight);
+       a.numer = s->font_stdnumer;
+       a.denom = s->font_stddenom;
+       break;
+      case LATTR_WIDE:
+       TextSize(s->cfg.fontheight);
+       a.numer = s->font_widenumer;
+       a.denom = s->font_widedenom;
+       break;
+      case LATTR_TOP:
+      case LATTR_BOT:
+       TextSize(s->cfg.fontheight * 2);
+       a.numer = s->font_bignumer;
+       a.denom = s->font_bigdenom;
+       break;
+    }
     SetPort(s->window);
     TextFont(s->fontnum);
     if (s->cfg.fontisbold || (attr & ATTR_BOLD) && !s->cfg.bold_colour)
@@ -1044,7 +1062,6 @@ void do_text(Context ctx, int x, int y, char *text, int len,
     if (attr & ATTR_UNDER)
        style |= underline;
     TextFace(style);
-    TextSize(s->cfg.fontheight);
     TextMode(srcOr);
     if (HAVE_COLOR_QD())
        if (style & bold) {
@@ -1054,12 +1071,17 @@ void do_text(Context ctx, int x, int y, char *text, int len,
            SpaceExtra(0);
            CharExtra(0);
        }
+    saveclip = NewRgn();
+    GetClip(saveclip);
+    ClipRect(&a.textrect);
     textrgn = NewRgn();
     RectRgn(textrgn, &a.textrect);
     if (HAVE_COLOR_QD())
        DeviceLoop(textrgn, &do_text_for_device_upp, (long)&a, 0);
     else
        do_text_for_device(1, 0, NULL, (long)&a);
+    SetClip(saveclip);
+    DisposeRgn(saveclip);
     DisposeRgn(textrgn);
     /* Tell the window manager about it in case this isn't an update */
     ValidRect(&a.textrect);
@@ -1115,7 +1137,19 @@ static pascal void do_text_for_device(short depth, short devflags,
     }
 
     EraseRect(&a->textrect);
-    MoveTo(a->textrect.left, a->textrect.top + a->s->font_ascent);
+    switch (a->lattr & LATTR_MODE) {
+      case LATTR_NORM:
+      case LATTR_WIDE:
+       MoveTo(a->textrect.left, a->textrect.top + a->s->font_ascent);
+       break;
+      case LATTR_TOP:
+       MoveTo(a->textrect.left, a->textrect.top + a->s->font_ascent * 2);
+       break;
+      case LATTR_BOT:
+       MoveTo(a->textrect.left,
+              a->textrect.top - a->s->font_height + a->s->font_ascent * 2);
+       break;
+    }
     /* FIXME: Sort out bold width adjustments on Original QuickDraw. */
     if (a->s->window->grafProcs != NULL)
        InvokeQDTextUPP(a->len, a->text, a->numer, a->denom,
@@ -1269,7 +1303,7 @@ void set_title(void *frontend, char *title) {
     Session *s = frontend;
     Str255 mactitle;
 
-    mactitle[0] = sprintf((char *)&mactitle[1], "%s", title);
+    c2pstrcpy(mactitle, title);
     SetWTitle(s->window, mactitle);
 }
 
@@ -1290,8 +1324,7 @@ void set_raw_mouse_mode(void *frontend, int activate)
 void request_resize(void *frontend, int w, int h) {
     Session *s = frontend;
 
-    s->term->cols = w;
-    s->term->rows = h;
+    term_size(s->term, h, w, s->cfg.savelines);
     mac_initfont(s);
 }
 
@@ -1402,9 +1435,12 @@ void get_window_pixels(void *frontend, int *x, int *y)
 char *get_window_title(void *frontend, int icon)
 {
     Session *s = frontend;
+    Str255 ptitle;
+    static char title[256];
 
-    /* Erm, we don't save this at the moment */
-    return "";
+    GetWTitle(s->window, ptitle);
+    p2cstrcpy(title, ptitle);
+    return title;
 }
 
 /*