Improve socket error handling so that a socket error isn't an
[u/mdw/putty] / winctrls.c
index 3a59503..3e4ce5d 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <windows.h>
+#include <commctrl.h>
 
 #include "winstuff.h"
 
@@ -18,6 +19,7 @@
 #define EDITHEIGHT 12
 #define COMBOHEIGHT 12
 #define PUSHBTNHEIGHT 14
+#define PROGBARHEIGHT 14
 
 void ctlposinit(struct ctlpos *cp, HWND hwnd,
                 int leftborder, int rightborder, int topborder) {
@@ -70,17 +72,16 @@ void bartitle(struct ctlpos *cp, char *name, int id) {
 /*
  * Begin a grouping box, with or without a group title.
  */
-void beginbox(struct ctlpos *cp, char *name, int idbox, int idtext) {
-    if (name)
-        cp->ypos += STATICHEIGHT/2;
+void beginbox(struct ctlpos *cp, char *name, int idbox) {
     cp->boxystart = cp->ypos;
+    if (!name)
+        cp->boxystart -= STATICHEIGHT/2;
     if (name)
-        cp->ypos += STATICHEIGHT - (STATICHEIGHT/2);
+        cp->ypos += STATICHEIGHT;
     cp->ypos += GAPYBOX;
     cp->width -= 2*GAPXBOX;
     cp->xoff += GAPXBOX;
     cp->boxid = idbox;
-    cp->boxtextid = idtext;
     cp->boxtext = name;
 }
 
@@ -94,25 +95,8 @@ void endbox(struct ctlpos *cp) {
     cp->ypos += GAPYBOX - GAPBETWEEN;
     r.left = GAPBETWEEN; r.right = cp->width;
     r.top = cp->boxystart; r.bottom = cp->ypos - cp->boxystart;
-    doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE | SS_ETCHEDFRAME, 0,
-          "", cp->boxid);
-    if (cp->boxtext) {
-        SIZE s;
-        HDC hdc;
-        HFONT oldfont, dlgfont;
-        hdc = GetDC(cp->hwnd);
-        dlgfont = (HFONT)cp->font;
-        oldfont = SelectObject(hdc, dlgfont);
-        GetTextExtentPoint32(hdc, cp->boxtext, strlen(cp->boxtext), &s);
-        SelectObject(hdc, oldfont);
-        DeleteDC(hdc);
-        r.left = GAPXBOX + GAPBETWEEN;
-        r.right = (s.cx * 4 + cp->dlu4inpix-1) / cp->dlu4inpix;
-        
-        r.top = cp->boxystart - STATICHEIGHT/2; r.bottom = STATICHEIGHT;
-        doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0,
-              cp->boxtext, cp->boxtextid);
-    }
+    doctl(cp, r, "BUTTON", BS_GROUPBOX | WS_CHILD | WS_VISIBLE, 0,
+          cp->boxtext ? cp->boxtext : "", cp->boxid);
     cp->ypos += GAPYBOX;
 }
 
@@ -247,6 +231,18 @@ void checkbox(struct ctlpos *cp, char *text, int id) {
 }
 
 /*
+ * A single standalone static text control.
+ */
+void statictext(struct ctlpos *cp, char *text, int id) {
+    RECT r;
+
+    r.left = GAPBETWEEN; r.top = cp->ypos;
+    r.right = cp->width; r.bottom = STATICHEIGHT;
+    cp->ypos += r.bottom + GAPBETWEEN;
+    doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, id);
+}
+
+/*
  * A button on the right hand side, with a static to its left.
  */
 void staticbtn(struct ctlpos *cp, char *stext, int sid,
@@ -277,8 +273,9 @@ void staticbtn(struct ctlpos *cp, char *stext, int sid,
 /*
  * An edit control on the right hand side, with a static to its left.
  */
-void staticedit(struct ctlpos *cp, char *stext,
-                int sid, int eid, int percentedit) {
+static void staticedit_internal(struct ctlpos *cp, char *stext,
+                                int sid, int eid, int percentedit,
+                                int style) {
     const int height = (EDITHEIGHT > STATICHEIGHT ?
                         EDITHEIGHT : STATICHEIGHT);
     RECT r;
@@ -295,13 +292,44 @@ void staticedit(struct ctlpos *cp, char *stext,
     r.left = rpos; r.top = cp->ypos + (height-EDITHEIGHT)/2;
     r.right = rwid; r.bottom = EDITHEIGHT;
     doctl(cp, r, "EDIT",
-          WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
+          WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL | style,
           WS_EX_CLIENTEDGE,
           "", eid);
 
     cp->ypos += height + GAPBETWEEN;
 }
 
+void staticedit(struct ctlpos *cp, char *stext,
+                int sid, int eid, int percentedit) {
+    staticedit_internal(cp, stext, sid, eid, percentedit, 0);
+}
+
+void staticpassedit(struct ctlpos *cp, char *stext,
+                    int sid, int eid, int percentedit) {
+    staticedit_internal(cp, stext, sid, eid, percentedit, ES_PASSWORD);
+}
+
+/*
+ * A big multiline edit control with a static labelling it.
+ */
+void bigeditctrl(struct ctlpos *cp, char *stext,
+                 int sid, int eid, int lines) {
+    RECT r;
+
+    r.left = GAPBETWEEN; r.top = cp->ypos;
+    r.right = cp->width; r.bottom = STATICHEIGHT;
+    cp->ypos += r.bottom + GAPWITHIN;
+    doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
+
+    r.left = GAPBETWEEN; r.top = cp->ypos;
+    r.right = cp->width; r.bottom = EDITHEIGHT + (lines-1) * STATICHEIGHT;
+    cp->ypos += r.bottom + GAPBETWEEN;
+    doctl(cp, r, "EDIT",
+          WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | ES_MULTILINE,
+          WS_EX_CLIENTEDGE,
+          "", eid);
+}
+
 /*
  * A tab-control substitute when a real tab control is unavailable.
  */
@@ -600,7 +628,7 @@ void colouredit(struct ctlpos *cp, char *stext, int sid, int listid,
     r.right = lwid; r.bottom = LISTHEIGHT;
     doctl(cp, r, "LISTBOX",
           WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_HASSTRINGS |
-          LBS_USETABSTOPS,
+          LBS_USETABSTOPS | LBS_NOTIFY,
           WS_EX_CLIENTEDGE,
           "", listid);
 
@@ -633,3 +661,22 @@ void colouredit(struct ctlpos *cp, char *stext, int sid, int listid,
     cp->ypos += LISTHEIGHT + GAPBETWEEN;
 }
 
+/*
+ * A progress bar (from Common Controls). We like our progress bars
+ * to be smooth and unbroken, without those ugly divisions; some
+ * older compilers may not support that, but that's life.
+ */
+void progressbar(struct ctlpos *cp, int id) {
+    RECT r;
+
+    r.left = GAPBETWEEN; r.top = cp->ypos;
+    r.right = cp->width; r.bottom = PROGBARHEIGHT;
+    cp->ypos += r.bottom + GAPBETWEEN;
+
+    doctl(cp, r, PROGRESS_CLASS,
+          WS_CHILD | WS_VISIBLE
+#ifdef PBS_SMOOTH
+          | PBS_SMOOTH
+#endif
+          , WS_EX_CLIENTEDGE, "", id);
+}