diff options
author | Theodore Tso <tytso@mit.edu> | 1998-05-27 19:23:34 +0000 |
---|---|---|
committer | Theodore Tso <tytso@mit.edu> | 1998-05-27 19:23:34 +0000 |
commit | f6e7e6667ed480c99c05b736c5fb568a48a55f23 (patch) | |
tree | 95ccf899fe5242e5d04dfc59d6bd9724d99a8788 /src/windows/lib/vardlg.c | |
parent | bd90cbd829ef4b7b440f56c754904227448a201f (diff) | |
download | krb5-f6e7e6667ed480c99c05b736c5fb568a48a55f23.tar.gz krb5-f6e7e6667ed480c99c05b736c5fb568a48a55f23.tar.xz krb5-f6e7e6667ed480c99c05b736c5fb568a48a55f23.zip |
Check in files from Kerbnet-1.2 release. This is an auxiliary library
used by some of the windows programs.
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@10589 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/windows/lib/vardlg.c')
-rw-r--r-- | src/windows/lib/vardlg.c | 450 |
1 files changed, 450 insertions, 0 deletions
diff --git a/src/windows/lib/vardlg.c b/src/windows/lib/vardlg.c new file mode 100644 index 0000000000..41d897bf7b --- /dev/null +++ b/src/windows/lib/vardlg.c @@ -0,0 +1,450 @@ +/* + * Dialog box building for various numbers of (label, entry) fields. + * + * This code is somewhat hardcoded to build boxes for the krb5_get_init_creds() + * function. + * + * Copyright (C) 1997 Cygnus Solutions. + * + * Author: Michael Graff + */ + +#include <windows.h> +#include <windowsx.h> + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "krb5.h" +#include "vardlg.h" + +/* + * a hack, I know... No error checking below, either. + */ +static unsigned char dlg[DLG_BUF]; + +/* + * Add a WORD (16-bit int) to the buffer. Return the number of characters + * added. + */ +static int +ADD_WORD(unsigned char *p, WORD w) +{ + *((WORD *)p) = w; + + return 2; +} + +static int +ADD_DWORD(unsigned char *p, DWORD dw) +{ + *((DWORD *)p) = dw; + + return 4; +} + +static int +ADD_UNICODE_STRING(unsigned char *p, const char *s) +{ + WORD *w; + int i; + int len; + + w = (WORD *)p; + + len = strlen(s) + 1; /* copy the null, too */ + + for (i = 0 ; i < len ; i++) + *w++ = *s++; + + return (len * 2); +} + +#define DWORD_ALIGN(p) { while ((DWORD)p % 4) *p++ = 0x00; } + +static int +ADD_DLGTEMPLATE(unsigned char *dlg, short x, short y, short cx, short cy, + const char *caption, const char *fontname, WORD fontsize, + WORD n) +{ + unsigned char *p; + DLGTEMPLATE dlt; + + p = dlg; + + dlt.style = (DS_MODALFRAME | WS_POPUP); + if (caption != NULL) + dlt.style |= WS_CAPTION; + if (fontname != NULL) + dlt.style |= DS_SETFONT; + dlt.dwExtendedStyle = 0; + dlt.cdit = n; + dlt.x = x; + dlt.y = y; + dlt.cx = cx; + dlt.cy = cy; + memcpy(p, &dlt, sizeof(dlt)); + p += sizeof(dlt); + + p += ADD_WORD(p, 0x0000); /* menu == none */ + + p += ADD_WORD(p, 0x0000); /* class == default? */ + + if (caption != NULL) + p += ADD_UNICODE_STRING(p, caption); + else + p += ADD_WORD(p, 0x0000); + + if (fontname != NULL) { + p += ADD_WORD(p, fontsize); + p += ADD_UNICODE_STRING(p, fontname); + } + + DWORD_ALIGN(p); + + return (p - dlg); +} + +static int +ADD_DLGITEM(unsigned char *dlg, short x, short y, short cx, short cy, + const char *label, WORD id, WORD type, DWORD style) +{ + unsigned char *p; + DLGITEMTEMPLATE dit; + + p = dlg; + + dit.style = style; + dit.dwExtendedStyle = 0; + dit.x = x; + dit.y = y; + dit.cx = cx; + dit.cy = cy; + dit.id = id; + memcpy(p, &dit, sizeof(dit)); + p += sizeof(dit); + + p += ADD_WORD(p, 0xffff); + p += ADD_WORD(p, type); + + p += ADD_UNICODE_STRING(p, label); + + /* + * creation data? For now, just make this empty, like the resource + * compiler does. + */ + p += ADD_WORD(p, 0x0000); + + DWORD_ALIGN(p); + + return (p - dlg); +} + +#define ADD_DLGITEM_defpushbutton(a, b, c, d, e, f, g) \ + ADD_DLGITEM((a), (b), (c), (d), (e), (f), (g), 0x0080, 0x50010001); + +#define ADD_DLGITEM_pushbutton(a, b, c, d, e, f, g) \ + ADD_DLGITEM((a), (b), (c), (d), (e), (f), (g), 0x0080, 0x50010000); + +#define ADD_DLGITEM_left_static(a, b, c, d, e, f, g) \ + ADD_DLGITEM((a), (b), (c), (d), (e), (f), (g), 0x0082, 0x50020000); + +#define ADD_DLGITEM_centered_static(a, b, c, d, e, f, g) \ + ADD_DLGITEM((a), (b), (c), (d), (e), (f), (g), 0x0082, 0x50020001); + +#define ADD_DLGITEM_right_static(a, b, c, d, e, f, g) \ + ADD_DLGITEM((a), (b), (c), (d), (e), (f), (g), 0x0082, 0x50020002); + +#define ADD_DLGITEM_entry(a, b, c, d, e, f, g) \ + ADD_DLGITEM((a), (b), (c), (d), (e), (f), (g), 0x0081, 0x50810080); + +#define ADD_DLGITEM_hidden_entry(a, b, c, d, e, f, g) \ + ADD_DLGITEM((a), (b), (c), (d), (e), (f), (g), 0x0081, 0x508100a0); + + +/* + * "build" the dialog box. In this bit of code, we create the dialog box, + * create the OK button, and a static label for the banner text. + * + * If there are items, we also create a Cancel button and one (label, entry) + * fields for each item. + */ +void * +vardlg_build(WORD cx, const char *banner, WORD n, krb5_prompt prompts[], + WORD id) +{ + unsigned char *p; + WORD i; + + p = dlg; /* global */ + + if (cx < MIN_WIDTH) + cx = MIN_WIDTH; + if (cx > MAX_WIDTH) + cx = MAX_WIDTH; + + /* + * Store the dialog template + */ + p += ADD_DLGTEMPLATE(p, 0, 0, cx, 0, "KerbNet", "MS Sans Serif", 8, + (WORD)(n * 2 + 3)); + + /* + * Create a label for the banner. This will be ID (id). + */ + p += ADD_DLGITEM_left_static(p, 0, 0, 0, 0, "", id++); + + /* + * Each label field is ID (id + 1) + (item * 2), and each entry field + * is (id + 2) + (item * 2) + */ + for (i = 0 ; i < n ; i++) { + p += ADD_DLGITEM_right_static(p, 0, 0, 0, 0, "", id++); + if (prompts[i].hidden) { + p += ADD_DLGITEM_hidden_entry(p, 0, 0, 0, 0, "", id++); + } else { + p += ADD_DLGITEM_entry(p, 0, 0, 0, 0, "", id++); + } + } + + /* + * Create the OK and Cancel buttons. + */ + p += ADD_DLGITEM_defpushbutton(p, 0, 0, 0, 0, + "OK", IDOK); + if (n != 0) + p += ADD_DLGITEM_pushbutton(p, 0, 0, 0, 0, + "Cancel", IDCANCEL); + + return dlg; +} + +#define SPACE_Y 4 /* logical units */ +#define SPACE_X 4 /* logical units */ +#define ENTRY_PX 120 /* pixels */ +#define BUTTON_PX 70 /* pixels */ +#define BUTTON_PY 30 /* pixels */ + +void +vardlg_config(HWND hwnd, WORD width, const char *banner, WORD num_prompts, + krb5_prompt *prompts, WORD id) +{ + int n; + WORD cid; + HDC hdc; + SIZE csize; + SIZE maxsize; + LONG cx, cy; + LONG ccx, ccy; + LONG space_x, space_y; + LONG max_x, max_y; + LONG banner_y; + RECT rect; + int done; + const char *p; + + /* + * First, set the banner's text. + */ + Static_SetText(GetDlgItem(hwnd, id), banner); + + /* + * Next, run through the items and set their static text. + * Also, set the corresponding edit string and set the + * maximum input length. + */ + cid = (id + 1); + + for (n = 0 ; n < num_prompts ; n++) { + Static_SetText(GetDlgItem(hwnd, cid), prompts[n].prompt); + cid++; + Edit_SetText(GetDlgItem(hwnd, cid), ""); + Edit_LimitText(GetDlgItem(hwnd, cid), prompts[n].reply->length); + cid++; + } + + /* + * Now run through the entry fields and find the longest string. + */ + maxsize.cx = maxsize.cy = 0; + cid = (id + 1); + hdc = GetDC(GetDlgItem(hwnd, cid)); /* assume one label is the same as all the others */ + + for (n = 0 ; n < num_prompts ; n++) { + GetTextExtentPoint32(hdc, prompts[n].prompt, strlen(prompts[n].prompt), &csize); + if (csize.cx > maxsize.cx) + maxsize.cx = csize.cx; + if (csize.cy > maxsize.cy) + maxsize.cy = csize.cy; + } + +#if 0 + /* + * convert the maximum values into pixels. Ugh. + */ + rect.left = 0; + rect.top = 0; + rect.right = maxsize.cx; + rect.bottom = maxsize.cy; + MapDialogRect(hwnd, &rect); + + max_x = rect.right; + max_y = rect.bottom; +#else + max_x = maxsize.cx; + max_y = (long)(((double)maxsize.cy) * 1.5); +#endif + + /* + * convert the spacing values, too. Ugh. Ugh. + */ + rect.left = 0; + rect.top = 0; + rect.right = SPACE_X; + rect.bottom = SPACE_Y; + MapDialogRect(hwnd, &rect); + + space_x = rect.right; + space_y = rect.bottom; + + /* + * Now we know the maximum length of the string for the entry labels. Guestimate + * that the entry fields should be ENTRY_PX pixels long and resize the dialog + * window to fit the longest string plus the entry fields (plus a little for the + * spacing between the edges of the windows and the static and edit fields, and + * between the static and edit fields themselves.) + */ + cx = max_x + ENTRY_PX + (space_x * 3); + cy = (max_y + space_y) * num_prompts; + + /* + * resize the dialog box itself (take 1) + */ + SetWindowPos(hwnd, HWND_TOPMOST, + 0, 0, + cx + 10, cy + 30, + SWP_NOMOVE); + + /* + * position the dialog items. First, the banner. (take 1) + */ + SetWindowPos(GetDlgItem(hwnd, id), HWND_BOTTOM, + space_x, space_y, + (cx - space_x * 2), max_y, + 0); + + /* + * Now that the window for the banner is in place, convert the width into logical units + * and find out how many lines we need to reserve room for. + */ + done = 0; + p = banner; + banner_y = 0; + + do { + int nFit; + int pDx[128]; + + hdc = GetDC(GetDlgItem(hwnd, id)); + + GetTextExtentExPoint(hdc, p, strlen(p), cx, &nFit, + pDx, &csize); + + banner_y += csize.cy; + + p += nFit; + + } while (*p != 0); + + banner_y += space_y; + + /* + * position the banner (take 2) + */ + SetWindowPos(GetDlgItem(hwnd, id), HWND_BOTTOM, + space_x, space_y, + (cx - space_x * 2), banner_y, + 0); + + /* + * Don't forget to include the banner estimate and the buttons, too. Once again, + * assume the buttons are BUTTON_PY pixels high. The extra three space_y's are + * for between the top of the dialog and the banner, between the banner and the + * first label, and between the buttons and the bottom of the screen. + */ + cy += banner_y + BUTTON_PY + (space_y * 3); + + /* + * resize the dialog box itself (Again... ugh!) + */ + SetWindowPos(hwnd, HWND_TOPMOST, + 0, 0, + cx + 10, cy + 30, + SWP_NOMOVE); + + cid = (id + 1); + ccy = banner_y + (space_y * 2); + ccx = max_x + (space_x * 2); /* where the edit fields start */ + + for (n = 0 ; n < num_prompts ; n++) { + SetWindowPos(GetDlgItem(hwnd, cid), HWND_BOTTOM, + space_x, ccy, + max_x, max_y, 0); + cid++; + SetWindowPos(GetDlgItem(hwnd, cid), HWND_BOTTOM, + ccx, ccy, + ENTRY_PX, max_y - 3, 0); + cid++; + ccy += (max_y + space_y); + } + + /* + * Now the buttons. If there are any entries we will have both an OK and a + * Cancel button. If we don't have any entries, we will have only an OK. + */ + if (num_prompts == 0) { + SetWindowPos(GetDlgItem(hwnd, IDOK), HWND_BOTTOM, + (cx / 2), cy - space_y - BUTTON_PY, + BUTTON_PX, BUTTON_PY, 0); + } else { + SetWindowPos(GetDlgItem(hwnd, IDOK), HWND_BOTTOM, + space_x, cy - space_y - BUTTON_PY, + BUTTON_PX, BUTTON_PY, 0); + SetWindowPos(GetDlgItem(hwnd, IDCANCEL), HWND_BOTTOM, + cx - space_x - BUTTON_PX, cy - space_y - BUTTON_PY, + BUTTON_PX, BUTTON_PY, 0); + } + + return; +} + +/* + * To use these functions, first create the dialog box and entries. + * You will always get an OK button. If there are at least one item, + * you will also get a cancel button. The OK button is IDOK, and the cancel + * button is IDCANCEL, as usual. + * + * After calling bld_dlg, the banner will have ID "id", and the labels + * will be "1 + id + i * 2" (i is the entry number, starting with zero) and + * the entries will be "2 + id + i * 2". + * + * unsigned char *dlg = vardlg_build(minwidth, banner, num_prompts, + * krb5_prompt[], id); + * + * Then, "run" the dialog using: + * + * rc = DialogBoxIndirect(hinstance, (LPDLGTEMPLATE)dlg, + * HWND_DESKTOP, myDialogProc); + * + * Note that the vardlg_build function uses a static data area and so cannot + * be used more than once before the DialogBoxIndirect() procedure is called. + * I assume windows won't need that area after that call is complete. + * + * In the dialog's _initialization_ procedure, call + * + * vardlg_config(hwnd, banner, num_prompts, krb5_prompt[], id); + * + * This function will resize the various elements of the dialog and fill in the + * labels. + */ |