Convert keyboard events into Unicode properly. I can now type all manner of
[u/mdw/putty] / mac / macterm.c
index 4c46356..dde1530 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: macterm.c,v 1.57 2003/01/27 00:39:01 ben Exp $ */
+/* $Id: macterm.c,v 1.64 2003/02/04 00:01:33 ben Exp $ */
 /*
  * Copyright (c) 1999 Simon Tatham
  * Copyright (c) 1999, 2002 Ben Harris
@@ -207,17 +207,15 @@ static void mac_workoutfontscale(Session *s, int wantwidth,
 static UnicodeToTextFallbackUPP uni_to_font_fallback_upp;
 
 static void mac_initfont(Session *s) {
-    Str255 macfont;
     FontInfo fi;
     TextEncoding enc;
     OptionBits fbflags;
 
     SetPort(s->window);
-    c2pstrcpy(macfont, s->cfg.font);
-    GetFNum(macfont, &s->fontnum);
+    GetFNum(s->cfg.font.name, &s->fontnum);
     TextFont(s->fontnum);
-    TextFace(s->cfg.fontisbold ? bold : 0);
-    TextSize(s->cfg.fontheight);
+    TextFace(s->cfg.font.face);
+    TextSize(s->cfg.font.size);
     GetFontInfo(&fi);
     s->font_width = CharWidth('W'); /* Well, it's what NCSA uses. */
     s->font_ascent = fi.ascent;
@@ -227,10 +225,10 @@ static void mac_initfont(Session *s) {
                         &s->font_stdnumer, &s->font_stddenom);
     mac_workoutfontscale(s, s->font_width * 2,
                         &s->font_widenumer, &s->font_widedenom);
-    TextSize(s->cfg.fontheight * 2);
+    TextSize(s->cfg.font.size * 2);
     mac_workoutfontscale(s, s->font_width * 2,
                         &s->font_bignumer, &s->font_bigdenom);
-    TextSize(s->cfg.fontheight);
+    TextSize(s->cfg.font.size);
     if (!s->cfg.bold_colour) {
        TextFace(bold);
        s->font_boldadjust = s->font_width - CharWidth('W');
@@ -242,7 +240,7 @@ static void mac_initfont(Session *s) {
     if (mac_gestalts.encvvers != 0 &&
        UpgradeScriptInfoToTextEncoding(kTextScriptDontCare,
                                        kTextLanguageDontCare,
-                                       kTextRegionDontCare, macfont,
+                                       kTextRegionDontCare, s->cfg.font.name,
                                        &enc) == noErr &&
        CreateUnicodeToTextInfoByEncoding(enc, &s->uni_to_font) == noErr) {
        if (uni_to_font_fallback_upp == NULL)
@@ -257,12 +255,15 @@ static void mac_initfont(Session *s) {
            goto no_encv;
        }
     } else {
+       char cfontname[256];
+
       no_encv:
        s->uni_to_font = NULL;
+       p2cstrcpy(cfontname, s->cfg.font.name);
        s->font_charset =
            charset_from_macenc(FontToScript(s->fontnum),
                                GetScriptManagerVariable(smRegionCode),
-                               mac_gestalts.sysvers, s->cfg.font);
+                               mac_gestalts.sysvers, cfontname);
     }
 
     mac_adjustsize(s, s->term->rows, s->term->cols);
@@ -581,7 +582,7 @@ void write_clip(void *cookie, wchar_t *data, int len, int must_deselect)
     stsc->scrpStyleTab[0].scrpAscent = s->font_ascent;
     stsc->scrpStyleTab[0].scrpFont = s->fontnum;
     stsc->scrpStyleTab[0].scrpFace = 0;
-    stsc->scrpStyleTab[0].scrpSize = s->cfg.fontheight;
+    stsc->scrpStyleTab[0].scrpSize = s->cfg.font.size;
     stsc->scrpStyleTab[0].scrpColor.red = 0;
     stsc->scrpStyleTab[0].scrpColor.green = 0;
     stsc->scrpStyleTab[0].scrpColor.blue = 0;
@@ -688,11 +689,16 @@ void mac_keyterm(WindowPtr window, EventRecord *event) {
     Session *s = (Session *)GetWRefCon(window);
     Key_Sym keysym = PK_NULL;
     unsigned int mods = 0, flags = PKF_NUMLOCK;
-    wchar_t utxt[1];
+    UniChar utxt[1];
+    char txt[1];
+    size_t len = 0;
+    ScriptCode key_script;
 
     ObscureCursor();
 
+#if 0
     fprintf(stderr, "Got key event %08x\n", event->message);
+#endif
 
     /* No meta key yet -- that'll be rather fun. */
 
@@ -771,9 +777,52 @@ void mac_keyterm(WindowPtr window, EventRecord *event) {
       case 0x7E: keysym = PK_UP; break;
     }
 
-    /* XXX Map from key script to Unicode. */
-    utxt[0] = event->message & charCodeMask;
-    term_key(s->term, keysym, utxt, 1, mods, flags);
+    /* Map from key script to Unicode. */
+    txt[0] = event->message & charCodeMask;
+    key_script = GetScriptManagerVariable(smKeyScript);
+
+    if (mac_gestalts.encvvers != 0) {
+       static TextToUnicodeInfo key_to_uni = NULL;
+       static ScriptCode key_to_uni_script;
+       TextEncoding enc;
+       ByteCount iread, olen;
+       OSErr err;
+
+       if (key_to_uni != NULL && key_to_uni_script != key_script)
+           DisposeTextToUnicodeInfo(&key_to_uni);
+        if (key_to_uni == NULL || key_to_uni_script != key_script) {
+           if (UpgradeScriptInfoToTextEncoding(key_script,
+                                               kTextLanguageDontCare,
+                                               kTextRegionDontCare, NULL,
+                                               &enc) == noErr &&
+               CreateTextToUnicodeInfoByEncoding(enc, &key_to_uni) == noErr)
+               key_to_uni_script = key_script;
+           else
+               key_to_uni = NULL;
+       }
+       if (key_to_uni != NULL) {
+           err = ConvertFromTextToUnicode(key_to_uni, 1, txt,
+                                          (kUnicodeKeepInfoMask |
+                                           kUnicodeStringUnterminatedMask),
+                                          0, NULL, NULL, NULL,
+                                          sizeof(utxt), &iread, &olen, utxt);
+           if (err == noErr)
+               len = olen / sizeof(*utxt);
+       }
+    } else {
+       int charset;
+       char *tptr = txt;
+       int tlen = 1;
+
+       charset = charset_from_macenc(key_script,
+                                     GetScriptManagerVariable(smRegionCode),
+                                     mac_gestalts.sysvers, NULL);
+       if (charset != CS_NONE) {
+           len = charset_to_unicode(&tptr, &tlen, utxt, sizeof(utxt), charset,
+                                    NULL, NULL, 0);
+       }
+    }
+    term_key(s->term, keysym, utxt, len, mods, flags);
 }
 
 void request_paste(void *frontend)
@@ -973,7 +1022,7 @@ struct do_text_args {
 void do_text(Context ctx, int x, int y, char *text, int len,
             unsigned long attr, int lattr) {
     Session *s = ctx;
-    int style = 0;
+    int style;
     struct do_text_args a;
     RgnHandle textrgn, saveclip;
     char mactextbuf[1024];
@@ -1027,25 +1076,26 @@ void do_text(Context ctx, int x, int y, char *text, int len,
     a.lattr = lattr;
     switch (lattr & LATTR_MODE) {
       case LATTR_NORM:
-       TextSize(s->cfg.fontheight);
+       TextSize(s->cfg.font.size);
        a.numer = s->font_stdnumer;
        a.denom = s->font_stddenom;
        break;
       case LATTR_WIDE:
-       TextSize(s->cfg.fontheight);
+       TextSize(s->cfg.font.size);
        a.numer = s->font_widenumer;
        a.denom = s->font_widedenom;
        break;
       case LATTR_TOP:
       case LATTR_BOT:
-       TextSize(s->cfg.fontheight * 2);
+       TextSize(s->cfg.font.size * 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)
+    style = s->cfg.font.face;
+    if ((attr & ATTR_BOLD) && !s->cfg.bold_colour)
        style |= bold;
     if (attr & ATTR_UNDER)
        style |= underline;
@@ -1090,8 +1140,10 @@ static pascal void do_text_for_device(short depth, short devflags,
 
     if (HAVE_COLOR_QD()) {
        if (depth > 2) {
-           fgcolour = ((a->attr & ATTR_FGMASK) >> ATTR_FGSHIFT) * 2;
-           bgcolour = ((a->attr & ATTR_BGMASK) >> ATTR_BGSHIFT) * 2;
+           fgcolour = ((a->attr & ATTR_FGMASK) >> ATTR_FGSHIFT);
+           fgcolour = (fgcolour & 0xF) * 2 + (fgcolour & 0x10 ? 1 : 0);
+           bgcolour = ((a->attr & ATTR_BGMASK) >> ATTR_BGSHIFT);
+           bgcolour = (bgcolour & 0xF) * 2 + (bgcolour & 0x10 ? 1 : 0);
        } else {
            /*
             * NB: bold reverse in 2bpp breaks with the usual PuTTY model and
@@ -1106,7 +1158,7 @@ static pascal void do_text_for_device(short depth, short devflags,
            bgcolour = tmp;
        }
        if (bright && depth > 2)
-           fgcolour++;
+           fgcolour |= 1;
        if ((a->attr & TATTR_ACTCURS) && depth > 1) {
            fgcolour = CURSOR_FG;
            bgcolour = CURSOR_BG;
@@ -1502,8 +1554,8 @@ void palette_reset(void *frontend) {
  * Scroll the screen. (`lines' is +ve for scrolling forward, -ve
  * for backward.)
  */
-void do_scroll(void *frontend, int topline, int botline, int lines) {
-    Session *s = frontend;
+void do_scroll(Context ctx, int topline, int botline, int lines) {
+    Session *s = ctx;
     Rect r;
     RgnHandle scrollrgn = NewRgn();
     RgnHandle movedupdate = NewRgn();
@@ -1590,7 +1642,7 @@ void frontend_keypress(void *handle)
  * Ask whether to wipe a session log file before writing to it.
  * Returns 2 for wipe, 1 for append, 0 for cancel (don't log).
  */
-int askappend(void *frontend, char *filename)
+int askappend(void *frontend, Filename filename)
 {
 
     /* FIXME: not implemented yet. */