Add support for labels on editboxes and radios.
[sgt/putty] / mac / macctrls.c
index 4aa9ce9..4b6c382 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: macctrls.c,v 1.16 2003/03/28 00:06:17 ben Exp $ */
+/* $Id: macctrls.c,v 1.19 2003/03/29 20:16:51 ben Exp $ */
 /*
  * Copyright (c) 2003 Ben Harris
  * All rights reserved.
@@ -76,10 +76,12 @@ union macctrl {
     struct {
        struct macctrl_generic generic;
        ControlRef tbctrl;
+       ControlRef tblabel;
     } editbox;
     struct {
        struct macctrl_generic generic;
        ControlRef *tbctrls;
+       ControlRef tblabel;
     } radio;
     struct {
        struct macctrl_generic generic;
@@ -117,6 +119,7 @@ struct mac_layoutstate {
 static void macctrl_layoutset(struct mac_layoutstate *, struct controlset *, 
                              WindowPtr, struct macctrls *);
 static void macctrl_switchtopanel(struct macctrls *, unsigned int);
+static void macctrl_setfocus(struct macctrls *, union macctrl *);
 static void macctrl_text(struct macctrls *, WindowPtr,
                         struct mac_layoutstate *, union control *);
 static void macctrl_editbox(struct macctrls *, WindowPtr,
@@ -218,6 +221,7 @@ void macctrl_layoutbox(struct controlbox *cb, WindowPtr window,
        CreateRootControl(window, &root);
     mcs->window = window;
     mcs->byctrl = newtree234(macctrl_cmp_byctrl);
+    mcs->focus = NULL;
     /* Count the number of panels */
     mcs->npanels = 1;
     for (i = 1; i < cb->nctrlsets; i++)
@@ -235,7 +239,7 @@ void macctrl_layoutbox(struct controlbox *cb, WindowPtr window,
        }
        macctrl_layoutset(&curstate, cb->ctrlsets[i], window, mcs);
     }
-    macctrl_switchtopanel(mcs, 1);
+    macctrl_switchtopanel(mcs, 14);
 }
 
 static void macctrl_layoutset(struct mac_layoutstate *curstate,
@@ -306,17 +310,23 @@ static void macctrl_switchtopanel(struct macctrls *mcs, unsigned int which)
     mcs->curpanel = which;
     /* Panel 0 is special and always visible. */
     for (i = 1; i < mcs->npanels; i++)
-       for (mc = mcs->panels[i]; mc != NULL; mc = mc->generic.next)
+       for (mc = mcs->panels[i]; mc != NULL; mc = mc->generic.next) {
+#if !TARGET_API_MAC_CARBON
+           if (mcs->focus == mc)
+               macctrl_setfocus(mcs, NULL);
+#endif
            switch (mc->generic.type) {
              case MACCTRL_TEXT:
                hideshow(mc->text.tbctrl);
                break;
              case MACCTRL_EDITBOX:
                hideshow(mc->editbox.tbctrl);
+               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);
                break;
              case MACCTRL_CHECKBOX:
                hideshow(mc->checkbox.tbctrl);
@@ -328,8 +338,46 @@ static void macctrl_switchtopanel(struct macctrls *mcs, unsigned int which)
                hideshow(mc->popup.tbctrl);
                break;
            }
+       }
+}
+
+#if !TARGET_API_MAC_CARBON
+/*
+ * System 7 focus manipulation
+ */
+static void macctrl_defocus(union macctrl *mc)
+{
+
+    assert(mac_gestalts.apprvers < 0x100);
+    switch (mc->generic.type) {
+      case MACCTRL_EDITBOX:
+       TEDeactivate((TEHandle)(*mc->editbox.tbctrl)->contrlData);
+       break;
+    }
+}
+
+static void macctrl_enfocus(union macctrl *mc)
+{
+
+    assert(mac_gestalts.apprvers < 0x100);
+    switch (mc->generic.type) {
+      case MACCTRL_EDITBOX:
+       TEActivate((TEHandle)(*mc->editbox.tbctrl)->contrlData);
+       break;
+    }
 }
 
+static void macctrl_setfocus(struct macctrls *mcs, union macctrl *mc)
+{
+
+    if (mcs->focus != NULL)
+       macctrl_defocus(mcs->focus);
+    mcs->focus = mc;
+    if (mc != NULL)
+       macctrl_enfocus(mc);
+}
+#endif
+
 static void macctrl_text(struct macctrls *mcs, WindowPtr window,
                         struct mac_layoutstate *curstate,
                         union control *ctrl)
@@ -410,7 +458,7 @@ static void macctrl_editbox(struct macctrls *mcs, WindowPtr window,
                            union control *ctrl)
 {
     union macctrl *mc = smalloc(sizeof *mc);
-    Rect bounds;
+    Rect lbounds, bounds;
 
     fprintf(stderr, "    label = %s\n", ctrl->editbox.label);
     fprintf(stderr, "    percentwidth = %d\n", ctrl->editbox.percentwidth);
@@ -419,19 +467,42 @@ static void macctrl_editbox(struct macctrls *mcs, WindowPtr window,
     mc->generic.type = MACCTRL_EDITBOX;
     mc->generic.ctrl = ctrl;
     mc->generic.privdata = NULL;
-    bounds.left = curstate->pos.h;
-    bounds.right = bounds.left + curstate->width;
+    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;
+       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;
+       lbounds.bottom = lbounds.top + 22;
+       bounds.left = lbounds.right;
+       bounds.right = lbounds.left + curstate->width;
+    }
     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);
-       mc->text.tbctrl = NewControl(window, &bounds, NULL, TRUE, 0, 0, 0,
-                                    ctrl->editbox.password ?
-                                    kControlEditTextPasswordProc :
-                                    kControlEditTextProc, (long)mc);
+       mc->editbox.tbctrl = NewControl(window, &bounds, NULL, TRUE, 0, 0, 0,
+                                       ctrl->editbox.password ?
+                                       kControlEditTextPasswordProc :
+                                       kControlEditTextProc, (long)mc);
     } else {
-       mc->text.tbctrl = NewControl(window, &bounds, NULL, TRUE, 0, 0, 0,
-                                    SYS7_EDITBOX_PROC, (long)mc);
+       Str255 title;
+
+       c2pstrcpy(title, ctrl->editbox.label);
+       mc->editbox.tblabel = NewControl(window, &lbounds, title, TRUE,
+                                        0, 0, 0, SYS7_TEXT_PROC, (long)mc);
+       mc->editbox.tbctrl = NewControl(window, &bounds, NULL, TRUE, 0, 0, 0,
+                                       SYS7_EDITBOX_PROC, (long)mc);
     }
     curstate->pos.v += 28;
     add234(mcs->byctrl, mc);
@@ -450,6 +521,7 @@ static pascal SInt32 macctrl_sys7_editbox_cdef(SInt16 variant,
     Rect rect;
     TEHandle te;
     long ssfs;
+    Point mouse;
 
     switch (msg) {
       case initCntl:
@@ -473,6 +545,12 @@ static pascal SInt32 macctrl_sys7_editbox_cdef(SInt16 variant,
            TEUpdate(&rect, (TEHandle)(*control)->contrlData);
        }
        return 0;
+      case testCntl:
+       mouse.h = LoWord(param);
+       mouse.v = HiWord(param);
+       return
+           PtInRect(mouse, &(*(TEHandle)(*control)->contrlData)->viewRect) ?
+           kControlEditTextPart : kControlNoPart;
       case calcCRgns:
        if (param & (1 << 31)) {
            param &= ~(1 << 31);
@@ -510,6 +588,24 @@ static void macctrl_radio(struct macctrls *mcs, WindowPtr window,
     mc->radio.tbctrls =
        smalloc(sizeof(*mc->radio.tbctrls) * ctrl->radio.nbuttons);
     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);
+    }
+    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;
@@ -728,10 +824,12 @@ void macctrl_activate(WindowPtr window, EventRecord *event)
                break;
              case MACCTRL_EDITBOX:
                HiliteControl(mc->editbox.tbctrl, state);
+               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);
                break;
              case MACCTRL_CHECKBOX:
                HiliteControl(mc->checkbox.tbctrl, state);
@@ -763,6 +861,7 @@ void macctrl_click(WindowPtr window, EventRecord *event)
     GlobalToLocal(&mouse);
     part = FindControl(mouse, window, &control);
     if (control != NULL) {
+       mc = (union macctrl *)GetControlReference(control);
        if (mac_gestalts.apprvers >= 0x100) {
            if (GetControlFeatures(control, &features) == noErr &&
                (features & kControlSupportsFocus) &&
@@ -770,9 +869,19 @@ void macctrl_click(WindowPtr window, EventRecord *event)
                SetKeyboardFocus(window, control, part);
            trackresult = HandleControlClick(control, mouse, event->modifiers,
                                             (ControlActionUPP)-1);
-       } else
+       } else {
+#if !TARGET_API_MAC_CARBON
+           if (mc->generic.type == MACCTRL_EDITBOX &&
+               control == mc->editbox.tbctrl) {
+               TEHandle te = (TEHandle)(*control)->contrlData;
+
+               macctrl_setfocus(mcs, mc);
+               TEClick(mouse, !!(event->modifiers & shiftKey), te);
+               goto done;
+           }
+#endif
            trackresult = TrackControl(control, mouse, (ControlActionUPP)-1);
-       mc = (union macctrl *)GetControlReference(control);
+       }
        switch (mc->generic.type) {
          case MACCTRL_RADIO:
            if (trackresult != 0) {
@@ -801,6 +910,7 @@ void macctrl_click(WindowPtr window, EventRecord *event)
            break;
        }
     }
+  done:
     SetPort(saveport);
 }
 
@@ -1069,17 +1179,18 @@ void dlg_editbox_set(union control *ctrl, void *dlg, char const *text)
     assert(mc->generic.type == MACCTRL_EDITBOX);
     GetPort(&saveport);
     SetPort((GrafPtr)(GetWindowPort(mcs->window)));
-    if (mac_gestalts.apprvers >= 0x100) {
+    if (mac_gestalts.apprvers >= 0x100)
        SetControlData(mc->editbox.tbctrl, kControlEntireControl,
                       ctrl->editbox.password ?
                       kControlEditTextPasswordTag :
                       kControlEditTextTextTag,
                       strlen(text), text);
-    } else {
+#if !TARGET_API_MAC_CARBON
+    else
        TESetText(text, strlen(text),
                  (TEHandle)(*mc->editbox.tbctrl)->contrlData);
-    }
-       DrawOneControl(mc->editbox.tbctrl);
+#endif
+    DrawOneControl(mc->editbox.tbctrl);
     SetPort(saveport);
 }
 
@@ -1099,14 +1210,21 @@ void dlg_editbox_get(union control *ctrl, void *dlg, char *buffer, int length)
                           length - 1, buffer, &olen) != noErr)
            olen = 0;
        if (olen > length - 1)
-           buffer[length - 1] = '\0';
-       else
-           buffer[olen] = '\0';
-       buffer[olen] = '\0';
-    } else
-       buffer[0] = '\0';
+           olen = length - 1;
+    }
+#if !TARGET_API_MAC_CARBON
+    else {
+       TEHandle te = (TEHandle)(*mc->editbox.tbctrl)->contrlData;
+
+       olen = (*te)->teLength;
+       if (olen > length - 1)
+           olen = length - 1;
+       memcpy(buffer, *(*te)->hText, olen);
+    }
+#endif
+    buffer[olen] = '\0';
     fprintf(stderr, "dlg_editbox_get: %s\n", buffer);
-};
+}
 
 
 /*