On System 7, draw the default ring in grey if the window is disabled.
[sgt/putty] / mac / macctrls.c
index 4b6c382..ce3ac75 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: macctrls.c,v 1.19 2003/03/29 20:16:51 ben Exp $ */
+/* $Id: macctrls.c,v 1.29 2003/04/05 18:00:46 ben Exp $ */
 /*
  * Copyright (c) 2003 Ben Harris
  * All rights reserved.
@@ -29,6 +29,7 @@
 #include <Appearance.h>
 #include <Controls.h>
 #include <ControlDefinitions.h>
+#include <Events.h>
 #include <Menus.h>
 #include <Resources.h>
 #include <Script.h>
@@ -90,6 +91,7 @@ union macctrl {
     struct {
        struct macctrl_generic generic;
        ControlRef tbctrl;
+       ControlRef tbring;
     } button;
     struct {
        struct macctrl_generic generic;
@@ -133,8 +135,6 @@ static void macctrl_button(struct macctrls *, WindowPtr,
 static void macctrl_popup(struct macctrls *, WindowPtr,
                          struct mac_layoutstate *, union control *);
 #if !TARGET_API_MAC_CARBON
-static pascal SInt32 macctrl_sys7_text_cdef(SInt16, ControlRef,
-                                           ControlDefProcMessage, SInt32);
 static pascal SInt32 macctrl_sys7_editbox_cdef(SInt16, ControlRef,
                                               ControlDefProcMessage, SInt32);
 static pascal SInt32 macctrl_sys7_default_cdef(SInt16, ControlRef,
@@ -163,8 +163,6 @@ static void macctrl_init()
     PatchCDEF cdef;
 
     if (inited) return;
-    cdef = (PatchCDEF)GetResource(kControlDefProcResourceType, CDEF_Text);
-    (*cdef)->theUPP = NewControlDefProc(macctrl_sys7_text_cdef);
     cdef = (PatchCDEF)GetResource(kControlDefProcResourceType, CDEF_EditBox);
     (*cdef)->theUPP = NewControlDefProc(macctrl_sys7_editbox_cdef);
     cdef = (PatchCDEF)GetResource(kControlDefProcResourceType, CDEF_Default);
@@ -215,19 +213,21 @@ void macctrl_layoutbox(struct controlbox *cb, WindowPtr window,
     rect = window->portRect;
 #endif
     curstate.pos.h = rect.left + 13;
-    curstate.pos.v = rect.bottom - 59;
+    curstate.pos.v = rect.bottom - 33;
     curstate.width = rect.right - rect.left - (13 * 2);
     if (mac_gestalts.apprvers >= 0x100)
        CreateRootControl(window, &root);
     mcs->window = window;
     mcs->byctrl = newtree234(macctrl_cmp_byctrl);
     mcs->focus = NULL;
+    mcs->defbutton = NULL;
+    mcs->canbutton = NULL;
     /* Count the number of panels */
     mcs->npanels = 1;
     for (i = 1; i < cb->nctrlsets; i++)
        if (strcmp(cb->ctrlsets[i]->pathname, cb->ctrlsets[i-1]->pathname))
            mcs->npanels++;
-    mcs->panels = smalloc(sizeof(*mcs->panels) * mcs->npanels);
+    mcs->panels = snewn(mcs->npanels, union macctrl *);
     memset(mcs->panels, 0, sizeof(*mcs->panels) * mcs->npanels);
     curstate.panelnum = 0;
     for (i = 0; i < cb->nctrlsets; i++) {
@@ -239,14 +239,18 @@ void macctrl_layoutbox(struct controlbox *cb, WindowPtr window,
        }
        macctrl_layoutset(&curstate, cb->ctrlsets[i], window, mcs);
     }
-    macctrl_switchtopanel(mcs, 14);
+    macctrl_switchtopanel(mcs, 1);
+    /* 14 = proxies, 20 = SSH bugs */
 }
 
+#define MAXCOLS 16
+
 static void macctrl_layoutset(struct mac_layoutstate *curstate,
                              struct controlset *s,
                              WindowPtr window, struct macctrls *mcs)
 {
-    unsigned int i;
+    unsigned int i, j, ncols, colstart;
+    struct mac_layoutstate cols[MAXCOLS];
 
     fprintf(stderr, "--- begin set ---\n");
     fprintf(stderr, "pathname = %s\n", s->pathname);
@@ -255,11 +259,14 @@ static void macctrl_layoutset(struct mac_layoutstate *curstate,
     if (s->boxtitle)
        fprintf(stderr, "boxtitle = %s\n", s->boxtitle);
 
+    cols[0] = *curstate;
+    ncols = 1;
 
     for (i = 0; i < s->ncontrols; i++) {
        union control *ctrl = s->ctrls[i];
        char const *s;
 
+       colstart = COLUMN_START(ctrl->generic.column);
        switch (ctrl->generic.type) {
          case CTRL_TEXT: s = "text"; break;
          case CTRL_EDITBOX: s = "editbox"; break;
@@ -275,27 +282,55 @@ static void macctrl_layoutset(struct mac_layoutstate *curstate,
        }
        fprintf(stderr, "  control: %s\n", s);
        switch (ctrl->generic.type) {
+         case CTRL_COLUMNS:
+           if (ctrl->columns.ncols != 1) {
+               ncols = ctrl->columns.ncols;
+               fprintf(stderr, "  split to %d\n", ncols);
+               assert(ncols <= MAXCOLS);
+               for (j = 0; j < ncols; j++) {
+                   cols[j] = cols[0];
+                   if (j > 0)
+                       cols[j].pos.h = cols[j-1].pos.h + cols[j-1].width + 6;
+                   if (j == ncols - 1)
+                       cols[j].width = curstate->width -
+                           (cols[j].pos.h - curstate->pos.h);
+                   else
+                       cols[j].width = (curstate->width + 6) * 
+                           ctrl->columns.percentages[j] / 100 - 6;
+               }
+           } else {
+               fprintf(stderr, "  join\n");
+               for (j = 0; j < ncols; j++)
+                   if (cols[j].pos.v > cols[0].pos.v)
+                       cols[0].pos.v = cols[j].pos.v;
+               cols[0].width = curstate->width;
+               ncols = 1;
+           }
+           break;
          case CTRL_TEXT:
-           macctrl_text(mcs, window, curstate, ctrl);
+           macctrl_text(mcs, window, &cols[colstart], ctrl);
            break;
          case CTRL_EDITBOX:
-           macctrl_editbox(mcs, window, curstate, ctrl);
+           macctrl_editbox(mcs, window, &cols[colstart], ctrl);
            break;
          case CTRL_RADIO:
-           macctrl_radio(mcs, window, curstate, ctrl);
+           macctrl_radio(mcs, window, &cols[colstart], ctrl);
            break;
          case CTRL_CHECKBOX:
-           macctrl_checkbox(mcs, window, curstate, ctrl);
+           macctrl_checkbox(mcs, window, &cols[colstart], ctrl);
            break;
          case CTRL_BUTTON:
-           macctrl_button(mcs, window, curstate, ctrl);
+           macctrl_button(mcs, window, &cols[colstart], ctrl);
            break;
          case CTRL_LISTBOX:
            if (ctrl->listbox.height == 0)
-               macctrl_popup(mcs, window, curstate, ctrl);
+               macctrl_popup(mcs, window, &cols[colstart], ctrl);
            break;
        }
     }
+    for (j = 0; j < ncols; j++)
+       if (cols[j].pos.v > curstate->pos.v)
+           curstate->pos.v = cols[j].pos.v;
 }
 
 static void macctrl_switchtopanel(struct macctrls *mcs, unsigned int which)
@@ -321,12 +356,14 @@ static void macctrl_switchtopanel(struct macctrls *mcs, unsigned int which)
                break;
              case MACCTRL_EDITBOX:
                hideshow(mc->editbox.tbctrl);
-               hideshow(mc->editbox.tblabel);
+               if (mc->editbox.tblabel != NULL)
+                   hideshow(mc->editbox.tblabel);
                break;
              case MACCTRL_RADIO:
                for (j = 0; j < mc->generic.ctrl->radio.nbuttons; j++)
                    hideshow(mc->radio.tbctrls[j]);
-               hideshow(mc->radio.tblabel);
+               if (mc->radio.tblabel != NULL)
+                   hideshow(mc->radio.tblabel);
                break;
              case MACCTRL_CHECKBOX:
                hideshow(mc->checkbox.tbctrl);
@@ -382,9 +419,11 @@ static void macctrl_text(struct macctrls *mcs, WindowPtr window,
                         struct mac_layoutstate *curstate,
                         union control *ctrl)
 {
-    union macctrl *mc = smalloc(sizeof *mc);
+    union macctrl *mc = snew(union macctrl);
     Rect bounds;
+    SInt16 height;
 
+    assert(ctrl->text.label != NULL);
     fprintf(stderr, "    label = %s\n", ctrl->text.label);
     mc->generic.type = MACCTRL_TEXT;
     mc->generic.ctrl = ctrl;
@@ -394,7 +433,6 @@ static void macctrl_text(struct macctrls *mcs, WindowPtr window,
     bounds.top = curstate->pos.v;
     bounds.bottom = bounds.top + 16;
     if (mac_gestalts.apprvers >= 0x100) {
-       SInt16 height;
        Size olen;
 
        mc->text.tbctrl = NewControl(window, &bounds, NULL, TRUE, 0, 0, 0,
@@ -405,62 +443,35 @@ static void macctrl_text(struct macctrls *mcs, WindowPtr window,
        GetControlData(mc->text.tbctrl, kControlEntireControl,
                       kControlStaticTextTextHeightTag,
                       sizeof(height), &height, &olen);
-       fprintf(stderr, "    height = %d\n", height);
-       SizeControl(mc->text.tbctrl, curstate->width, height);
-       curstate->pos.v += height + 6;
-    } else {
-       Str255 title;
+    }
+#if !TARGET_API_MAC_CARBON
+    else {
+       TEHandle te;
 
-       c2pstrcpy(title, ctrl->text.label);
-       mc->text.tbctrl = NewControl(window, &bounds, title, TRUE, 0, 0, 0,
+       mc->text.tbctrl = NewControl(window, &bounds, NULL, TRUE, 0, 0, 0,
                                     SYS7_TEXT_PROC, (long)mc);
+       te = (TEHandle)(*mc->text.tbctrl)->contrlData;
+       TESetText(ctrl->text.label, strlen(ctrl->text.label), te);
+       height = TEGetHeight(1, (*te)->nLines, te);
     }
+#endif
+    fprintf(stderr, "    height = %d\n", height);
+    SizeControl(mc->text.tbctrl, curstate->width, height);
+    curstate->pos.v += height + 6;
     add234(mcs->byctrl, mc);
     mc->generic.next = mcs->panels[curstate->panelnum];
     mcs->panels[curstate->panelnum] = mc;
 }
 
-#if !TARGET_API_MAC_CARBON
-static pascal SInt32 macctrl_sys7_text_cdef(SInt16 variant, ControlRef control,
-                                    ControlDefProcMessage msg, SInt32 param)
-{
-    RgnHandle rgn;
-
-    switch (msg) {
-      case drawCntl:
-       if ((*control)->contrlVis)
-           TETextBox((*control)->contrlTitle + 1, (*control)->contrlTitle[0],
-                     &(*control)->contrlRect, teFlushDefault);
-       return 0;
-      case calcCRgns:
-       if (param & (1 << 31)) {
-           param &= ~(1 << 31);
-           goto calcthumbrgn;
-       }
-       /* FALLTHROUGH */
-      case calcCntlRgn:
-       rgn = (RgnHandle)param;
-       RectRgn(rgn, &(*control)->contrlRect);
-       return 0;
-      case calcThumbRgn:
-      calcthumbrgn:
-       rgn = (RgnHandle)param;
-       SetEmptyRgn(rgn);
-       return 0;
-    }
-
-    return 0;
-}
-#endif
-
 static void macctrl_editbox(struct macctrls *mcs, WindowPtr window,
                            struct mac_layoutstate *curstate,
                            union control *ctrl)
 {
-    union macctrl *mc = smalloc(sizeof *mc);
+    union macctrl *mc = snew(union macctrl);
     Rect lbounds, bounds;
 
-    fprintf(stderr, "    label = %s\n", ctrl->editbox.label);
+    if (ctrl->editbox.label != NULL)
+       fprintf(stderr, "    label = %s\n", ctrl->editbox.label);
     fprintf(stderr, "    percentwidth = %d\n", ctrl->editbox.percentwidth);
     if (ctrl->editbox.password) fprintf(stderr, "    password\n");
     if (ctrl->editbox.has_list) fprintf(stderr, "    has list\n");
@@ -470,11 +481,13 @@ static void macctrl_editbox(struct macctrls *mcs, WindowPtr window,
     lbounds.left = curstate->pos.h;
     lbounds.top = curstate->pos.v;
     if (ctrl->editbox.percentwidth == 100) {
-       lbounds.right = lbounds.left + curstate->width;
-       lbounds.bottom = lbounds.top + 16;
+       if (ctrl->editbox.label != NULL) {
+           lbounds.right = lbounds.left + curstate->width;
+           lbounds.bottom = lbounds.top + 16;
+           curstate->pos.v += 18;
+       }
        bounds.left = curstate->pos.h;
        bounds.right = bounds.left + curstate->width;
-       curstate->pos.v += 18;
     } else {
        lbounds.right = lbounds.left +
            curstate->width * (100 - ctrl->editbox.percentwidth) / 100;
@@ -485,25 +498,37 @@ static void macctrl_editbox(struct macctrls *mcs, WindowPtr window,
     bounds.top = curstate->pos.v;
     bounds.bottom = bounds.top + 22;
     if (mac_gestalts.apprvers >= 0x100) {
-       mc->editbox.tblabel = NewControl(window, &lbounds, NULL, TRUE, 0, 0, 0,
-                                        kControlStaticTextProc, (long)mc);
-       SetControlData(mc->editbox.tblabel, kControlEntireControl,
-                      kControlStaticTextTextTag,
-                      strlen(ctrl->editbox.label), ctrl->editbox.label);
-       InsetRect(&bounds, 2, 2);
+       if (ctrl->editbox.label == NULL)
+           mc->editbox.tblabel = NULL;
+       else {
+           mc->editbox.tblabel = NewControl(window, &lbounds, NULL, TRUE,
+                                            0, 0, 0, kControlStaticTextProc,
+                                            (long)mc);
+           SetControlData(mc->editbox.tblabel, kControlEntireControl,
+                          kControlStaticTextTextTag,
+                          strlen(ctrl->editbox.label), ctrl->editbox.label);
+       }
+       InsetRect(&bounds, 3, 3);
        mc->editbox.tbctrl = NewControl(window, &bounds, NULL, TRUE, 0, 0, 0,
                                        ctrl->editbox.password ?
                                        kControlEditTextPasswordProc :
                                        kControlEditTextProc, (long)mc);
-    } else {
-       Str255 title;
-
-       c2pstrcpy(title, ctrl->editbox.label);
-       mc->editbox.tblabel = NewControl(window, &lbounds, title, TRUE,
-                                        0, 0, 0, SYS7_TEXT_PROC, (long)mc);
+    }
+#if !TARGET_API_MAC_CARBON
+    else {
+       if (ctrl->editbox.label == NULL)
+           mc->editbox.tblabel = NULL;
+       else {
+           mc->editbox.tblabel = NewControl(window, &lbounds, NULL, TRUE,
+                                            0, 0, 0, SYS7_TEXT_PROC,
+                                            (long)mc);
+           TESetText(ctrl->editbox.label, strlen(ctrl->editbox.label),
+                     (TEHandle)(*mc->editbox.tblabel)->contrlData);
+       }
        mc->editbox.tbctrl = NewControl(window, &bounds, NULL, TRUE, 0, 0, 0,
                                        SYS7_EDITBOX_PROC, (long)mc);
     }
+#endif
     curstate->pos.v += 28;
     add234(mcs->byctrl, mc);
     mc->generic.next = mcs->panels[curstate->panelnum];
@@ -526,7 +551,8 @@ static pascal SInt32 macctrl_sys7_editbox_cdef(SInt16 variant,
     switch (msg) {
       case initCntl:
        rect = (*control)->contrlRect;
-       InsetRect(&rect, 3, 3); /* 2 if it's 20 pixels high */
+       if (variant == SYS7_EDITBOX_VARIANT)
+           InsetRect(&rect, 3, 3); /* 2 if it's 20 pixels high */
        te = TENew(&rect, &rect);
        ssfs = GetScriptVariable(smSystemScript, smScriptSysFondSize);
        (*te)->txSize = LoWord(ssfs);
@@ -539,18 +565,23 @@ static pascal SInt32 macctrl_sys7_editbox_cdef(SInt16 variant,
       case drawCntl:
        if ((*control)->contrlVis) {
            rect = (*control)->contrlRect;
-           PenNormal();
-           FrameRect(&rect);
-           InsetRect(&rect, 3, 3);
+           if (variant == SYS7_EDITBOX_VARIANT) {
+               PenNormal();
+               FrameRect(&rect);
+               InsetRect(&rect, 3, 3);
+           }
+           (*(TEHandle)(*control)->contrlData)->viewRect = rect;
            TEUpdate(&rect, (TEHandle)(*control)->contrlData);
        }
        return 0;
       case testCntl:
+       if (variant == SYS7_TEXT_VARIANT)
+           return kControlNoPart;
        mouse.h = LoWord(param);
        mouse.v = HiWord(param);
-       return
-           PtInRect(mouse, &(*(TEHandle)(*control)->contrlData)->viewRect) ?
-           kControlEditTextPart : kControlNoPart;
+       rect = (*control)->contrlRect;
+       InsetRect(&rect, 3, 3);
+       return PtInRect(mouse, &rect) ? kControlEditTextPart : kControlNoPart;
       case calcCRgns:
        if (param & (1 << 31)) {
            param &= ~(1 << 31);
@@ -576,36 +607,43 @@ static void macctrl_radio(struct macctrls *mcs, WindowPtr window,
                          struct mac_layoutstate *curstate,
                          union control *ctrl)
 {
-    union macctrl *mc = smalloc(sizeof *mc);
+    union macctrl *mc = snew(union macctrl);
     Rect bounds;
     Str255 title;
     unsigned int i, colwidth;
 
-    fprintf(stderr, "    label = %s\n", ctrl->radio.label);
+    if (ctrl->radio.label != NULL)
+       fprintf(stderr, "    label = %s\n", ctrl->radio.label);
     mc->generic.type = MACCTRL_RADIO;
     mc->generic.ctrl = ctrl;
     mc->generic.privdata = NULL;
-    mc->radio.tbctrls =
-       smalloc(sizeof(*mc->radio.tbctrls) * ctrl->radio.nbuttons);
+    mc->radio.tbctrls = snewn(ctrl->radio.nbuttons, ControlRef);
     colwidth = (curstate->width + 13) /        ctrl->radio.ncolumns;
     bounds.top = curstate->pos.v;
     bounds.bottom = bounds.top + 16;
     bounds.left = curstate->pos.h;
     bounds.right = bounds.left + curstate->width;
-    if (mac_gestalts.apprvers >= 0x100) {
-       mc->radio.tblabel = NewControl(window, &bounds, NULL, TRUE, 0, 0, 0,
-                                      kControlStaticTextProc, (long)mc);
-       SetControlData(mc->radio.tblabel, kControlEntireControl,
-                      kControlStaticTextTextTag,
-                      strlen(ctrl->radio.label), ctrl->radio.label);
-    } else {
-       Str255 title;
-
-       c2pstrcpy(title, ctrl->radio.label);
-       mc->editbox.tblabel = NewControl(window, &bounds, title, TRUE,
-                                        0, 0, 0, SYS7_TEXT_PROC, (long)mc);
+    if (ctrl->radio.label == NULL)
+       mc->radio.tblabel = NULL;
+    else {
+       if (mac_gestalts.apprvers >= 0x100) {
+           mc->radio.tblabel = NewControl(window, &bounds, NULL, TRUE,
+                                          0, 0, 0, kControlStaticTextProc,
+                                          (long)mc);
+           SetControlData(mc->radio.tblabel, kControlEntireControl,
+                          kControlStaticTextTextTag,
+                          strlen(ctrl->radio.label), ctrl->radio.label);
+       }
+#if !TARGET_API_MAC_CARBON
+       else {
+           mc->radio.tblabel = NewControl(window, &bounds, NULL, TRUE,
+                                          0, 0, 0, SYS7_TEXT_PROC, (long)mc);
+           TESetText(ctrl->radio.label, strlen(ctrl->radio.label),
+                     (TEHandle)(*mc->radio.tblabel)->contrlData);
+       }
+#endif
+       curstate->pos.v += 18;
     }
-    curstate->pos.v += 18;
     for (i = 0; i < ctrl->radio.nbuttons; i++) {
        fprintf(stderr, "    button = %s\n", ctrl->radio.buttons[i]);
        bounds.top = curstate->pos.v - 2;
@@ -632,10 +670,11 @@ static void macctrl_checkbox(struct macctrls *mcs, WindowPtr window,
                             struct mac_layoutstate *curstate,
                             union control *ctrl)
 {
-    union macctrl *mc = smalloc(sizeof *mc);
+    union macctrl *mc = snew(union macctrl);
     Rect bounds;
     Str255 title;
 
+    assert(ctrl->checkbox.label != NULL);
     fprintf(stderr, "    label = %s\n", ctrl->checkbox.label);
     mc->generic.type = MACCTRL_CHECKBOX;
     mc->generic.ctrl = ctrl;
@@ -658,10 +697,11 @@ static void macctrl_button(struct macctrls *mcs, WindowPtr window,
                           struct mac_layoutstate *curstate,
                           union control *ctrl)
 {
-    union macctrl *mc = smalloc(sizeof *mc);
+    union macctrl *mc = snew(union macctrl);
     Rect bounds;
     Str255 title;
 
+    assert(ctrl->button.label != NULL);
     fprintf(stderr, "    label = %s\n", ctrl->button.label);
     if (ctrl->button.isdefault)
        fprintf(stderr, "    is default\n");
@@ -669,12 +709,13 @@ static void macctrl_button(struct macctrls *mcs, WindowPtr window,
     mc->generic.ctrl = ctrl;
     mc->generic.privdata = NULL;
     bounds.left = curstate->pos.h;
-    bounds.right = bounds.left + 100; /* XXX measure string */
+    bounds.right = bounds.left + curstate->width;
     bounds.top = curstate->pos.v;
     bounds.bottom = bounds.top + 20;
     c2pstrcpy(title, ctrl->button.label);
     mc->button.tbctrl = NewControl(window, &bounds, title, TRUE, 0, 0, 1,
                                   pushButProc, (long)mc);
+    mc->button.tbring = NULL;
     if (mac_gestalts.apprvers >= 0x100) {
        Boolean isdefault = ctrl->button.isdefault;
 
@@ -683,8 +724,8 @@ static void macctrl_button(struct macctrls *mcs, WindowPtr window,
                       sizeof(isdefault), &isdefault);
     } else if (ctrl->button.isdefault) {
        InsetRect(&bounds, -4, -4);
-       NewControl(window, &bounds, title, TRUE, 0, 0, 1,
-                  SYS7_DEFAULT_PROC, (long)mc);
+       mc->button.tbring = NewControl(window, &bounds, title, TRUE, 0, 0, 1,
+                                      SYS7_DEFAULT_PROC, (long)mc);
     }
     if (mac_gestalts.apprvers >= 0x110) {
        Boolean iscancel = ctrl->button.iscancel;
@@ -693,6 +734,10 @@ static void macctrl_button(struct macctrls *mcs, WindowPtr window,
                       kControlPushButtonCancelTag,
                       sizeof(iscancel), &iscancel);
     }
+    if (ctrl->button.isdefault)
+       mcs->defbutton = mc;
+    if (ctrl->button.iscancel)
+       mcs->canbutton = mc;
     add234(mcs->byctrl, mc);
     mc->generic.next = mcs->panels[curstate->panelnum];
     mcs->panels[curstate->panelnum] = mc;
@@ -708,15 +753,20 @@ static pascal SInt32 macctrl_sys7_default_cdef(SInt16 variant,
     RgnHandle rgn;
     Rect rect;
     int oval;
+    PenState savestate;
 
     switch (msg) {
       case drawCntl:
        if ((*control)->contrlVis) {
            rect = (*control)->contrlRect;
+           GetPenState(&savestate);
            PenNormal();
            PenSize(3, 3);
+           if ((*control)->contrlHilite == kControlInactivePart)
+               PenPat(&qd.gray);
            oval = (rect.bottom - rect.top) / 2 + 2;
            FrameRoundRect(&rect, oval, oval);
+           SetPenState(&savestate);
        }
        return 0;
       case calcCRgns:
@@ -744,7 +794,7 @@ static void macctrl_popup(struct macctrls *mcs, WindowPtr window,
                          struct mac_layoutstate *curstate,
                          union control *ctrl)
 {
-    union macctrl *mc = smalloc(sizeof *mc);
+    union macctrl *mc = snew(union macctrl);
     Rect bounds;
     Str255 title;
     unsigned int labelwidth;
@@ -760,13 +810,14 @@ static void macctrl_popup(struct macctrls *mcs, WindowPtr window,
     assert(!ctrl->listbox.draglist);
     assert(!ctrl->listbox.multisel);
 
-    fprintf(stderr, "    label = %s\n", ctrl->listbox.label);
+    if (ctrl->listbox.label != NULL)
+       fprintf(stderr, "    label = %s\n", ctrl->listbox.label);
     fprintf(stderr, "    percentwidth = %d\n", ctrl->listbox.percentwidth);
 
     mc->generic.type = MACCTRL_POPUP;
     mc->generic.ctrl = ctrl;
     mc->generic.privdata = NULL;
-    c2pstrcpy(title, ctrl->button.label);
+    c2pstrcpy(title, ctrl->button.label == NULL ? "" : ctrl->button.label);
 
     /* Find a spare menu ID and create the menu */
     while (GetMenuHandle(nextmenuid) != NULL)
@@ -817,30 +868,43 @@ void macctrl_activate(WindowPtr window, EventRecord *event)
                                 TRUE);
     state = active ? kControlNoPart : kControlInactivePart;
     for (i = 0; i <= mcs->curpanel; i += mcs->curpanel)
-       for (mc = mcs->panels[i]; mc != NULL; mc = mc->generic.next)
+       for (mc = mcs->panels[i]; mc != NULL; mc = mc->generic.next) {
            switch (mc->generic.type) {
              case MACCTRL_TEXT:
                HiliteControl(mc->text.tbctrl, state);
                break;
              case MACCTRL_EDITBOX:
                HiliteControl(mc->editbox.tbctrl, state);
-               HiliteControl(mc->editbox.tblabel, state);
+               if (mc->editbox.tblabel != NULL)
+                   HiliteControl(mc->editbox.tblabel, state);
                break;
              case MACCTRL_RADIO:
                for (j = 0; j < mc->generic.ctrl->radio.nbuttons; j++)
                    HiliteControl(mc->radio.tbctrls[j], state);
-               HiliteControl(mc->radio.tblabel, state);
+               if (mc->radio.tblabel != NULL)
+                   HiliteControl(mc->radio.tblabel, state);
                break;
              case MACCTRL_CHECKBOX:
                HiliteControl(mc->checkbox.tbctrl, state);
                break;
              case MACCTRL_BUTTON:
                HiliteControl(mc->button.tbctrl, state);
+               if (mc->button.tbring != NULL)
+                   HiliteControl(mc->button.tbring, state);                
                break;
              case MACCTRL_POPUP:
                HiliteControl(mc->popup.tbctrl, state);
                break;
            }
+#if !TARGET_API_MAC_CARBON
+           if (mcs->focus == mc) {
+               if (active)
+                   macctrl_enfocus(mc);
+               else
+                   macctrl_defocus(mc);
+           }
+#endif
+       }
     SetPort(saveport);
 }
 
@@ -919,14 +983,58 @@ void macctrl_key(WindowPtr window, EventRecord *event)
     ControlRef control;
     struct macctrls *mcs = mac_winctrls(window);
     union macctrl *mc;
+    unsigned long dummy;
+
+    switch (event->message & charCodeMask) {
+      case kEnterCharCode:
+      case kReturnCharCode:
+       if (mcs->defbutton != NULL) {
+           assert(mcs->defbutton->generic.type == MACCTRL_BUTTON);
+           HiliteControl(mcs->defbutton->button.tbctrl, kControlButtonPart);
+           /*
+            * I'd like to delay unhilighting the button until after
+            * the event has been processed, but by them the entire
+            * dialgue box might have been destroyed.
+            */
+           Delay(6, &dummy);
+           HiliteControl(mcs->defbutton->button.tbctrl, kControlNoPart);
+           ctrlevent(mcs, mcs->defbutton, EVENT_ACTION);
+       }
+       return;
+      case kEscapeCharCode:
+       if (mcs->canbutton != NULL) {
+           assert(mcs->canbutton->generic.type == MACCTRL_BUTTON);
+           HiliteControl(mcs->canbutton->button.tbctrl, kControlButtonPart);
+           Delay(6, &dummy);
+           HiliteControl(mcs->defbutton->button.tbctrl, kControlNoPart);
+           ctrlevent(mcs, mcs->canbutton, EVENT_ACTION);
+       }
+       return;
+    }
+    if (mac_gestalts.apprvers >= 0x100) {
+       if (GetKeyboardFocus(window, &control) == noErr && control != NULL) {
+           HandleControlKey(control, (event->message & keyCodeMask) >> 8,
+                            event->message & charCodeMask, event->modifiers);
+           mc = (union macctrl *)GetControlReference(control);
+           ctrlevent(mcs, mc, EVENT_VALCHANGE);
+       }
+    }
+#if !TARGET_API_MAC_CARBON
+    else {
+       TEHandle te;
 
-    if (mac_gestalts.apprvers >= 0x100 &&
-       GetKeyboardFocus(window, &control) == noErr && control != NULL) {
-       HandleControlKey(control, (event->message & keyCodeMask) >> 8,
-                        event->message & charCodeMask, event->modifiers);
-       mc =  (union macctrl *)GetControlReference(control);
-       ctrlevent(mcs, mc, EVENT_VALCHANGE);
+       if (mcs->focus != NULL) {
+           mc = mcs->focus;
+           switch (mc->generic.type) {
+             case MACCTRL_EDITBOX:
+               te = (TEHandle)(*mc->editbox.tbctrl)->contrlData;
+               TEKey(event->message & charCodeMask, te);
+               ctrlevent(mcs, mc, EVENT_VALCHANGE);
+               break;
+           }
+       }
     }
+#endif
 }
 
 void macctrl_update(WindowPtr window)
@@ -1056,7 +1164,10 @@ void dlg_error_msg(void *dlg, char *msg)
 
 void dlg_end(void *dlg, int value)
 {
+    struct macctrls *mcs = dlg;
 
+    if (mcs->end != NULL)
+       (*mcs->end)(mcs->window, value);
 };
 
 void dlg_refresh(union control *ctrl, void *dlg)
@@ -1311,8 +1422,7 @@ static void dlg_macpopup_addwithid(union control *ctrl, void *dlg,
     index = CountMenuItems(menu) - 1;
     if (mc->popup.nids <= index) {
        mc->popup.nids = index + 1;
-       mc->popup.ids = srealloc(mc->popup.ids,
-                                mc->popup.nids * sizeof(*mc->popup.ids));
+       mc->popup.ids = sresize(mc->popup.ids, mc->popup.nids, int);
     }
     mc->popup.ids[index] = id;
 }
@@ -1375,16 +1485,16 @@ void dlg_text_set(union control *ctrl, void *dlg, char const *text)
 {
     struct macctrls *mcs = dlg;
     union macctrl *mc = findbyctrl(mcs, ctrl);
-    Str255 title;
 
     assert(mc != NULL);
     if (mac_gestalts.apprvers >= 0x100)
        SetControlData(mc->text.tbctrl, kControlEntireControl,
                       kControlStaticTextTextTag, strlen(text), text);
-    else {
-       c2pstrcpy(title, text);
-       SetControlTitle(mc->text.tbctrl, title);
-    }
+#if !TARGET_API_MAC_CARBON
+    else
+       TESetText(text, strlen(text),
+                 (TEHandle)(*mc->text.tbctrl)->contrlData);
+#endif
 }