diff options
Diffstat (limited to 'src/runtime/rmswin.ri')
-rw-r--r-- | src/runtime/rmswin.ri | 4204 |
1 files changed, 4204 insertions, 0 deletions
diff --git a/src/runtime/rmswin.ri b/src/runtime/rmswin.ri new file mode 100644 index 0000000..3471fd3 --- /dev/null +++ b/src/runtime/rmswin.ri @@ -0,0 +1,4204 @@ +/* + * rmswin.ri - Microsoft Windows-specific graphics interface code. + * + * Todo: + * geticonpos + * seticonimage + * free_mutable + * freecolor + * + * Untested: + * toggle_fgbg + * rebind + * geticonic + * getimstr + * getfntnam + * dumpimage + * getpointername + * + * Blown off: + * getvisual + * getdefault + */ +#ifdef Graphics + +void wfreersc(); +int alc_rgb(wbp w, SysColor rgb); +/* + * check_and_get_msg retreives the next message in *pMsg; + * returns 1 if regular message was retreived, 0 if quit message, + * -1 if there was an error. + */ +static int check_and_get_msg( MSG *pMsg ); +int numRealized; + +#ifndef min + #define min(x,y) (((x) < (y))?(x):(y)) + #define max(x,y) (((x) > (y))?(x):(y)) +#endif /* min */ +#define PALCLR(c) (c | 0x2000000L) + +int winInitialized = 0; +int BORDHEIGHT; +int BORDWIDTH; +/* + * check for double-byte character set versions of Windows + */ +CPINFO cpinfo; +int MAXBYTESPERCHAR; + +wclrp scp; +HPALETTE palette; +int numColors = 0; + +char szAppName[] = "Icon"; + +/* + * pattern symbols + */ +stringint siPatternSyms[] = { + {0, 16}, + { "black", 0}, + { "checkers", 12}, + { "darkgray", 2}, + { "diagonal", 8}, + { "grains", 13}, + { "gray", 3}, + { "grid", 10}, + { "horizontal",9}, + { "lightgray", 4}, + { "scales", 14}, + { "trellis", 11}, + { "vertical", 7}, + { "verydark", 1}, + { "verylight", 5}, + { "waves", 15}, + { "white", 6}, +}; + +/* + * draw ops + */ +stringint drawops[] = { + { 0, 16}, + {"and", R2_MASKPEN}, + {"andInverted", R2_MASKPENNOT}, + {"andReverse", R2_MASKNOTPEN}, + {"clear", R2_BLACK}, + {"copy", R2_COPYPEN}, + {"copyInverted", R2_NOTCOPYPEN}, + {"equiv", R2_NOTXORPEN}, + {"invert", R2_NOT}, + {"nand", R2_NOTMASKPEN}, + {"noop", R2_NOP}, + {"nor", R2_NOTMERGEPEN}, + {"or", R2_MERGEPEN}, + {"orInverted", R2_MERGEPENNOT}, + {"orReverse", R2_MERGENOTPEN}, + {"set", R2_WHITE}, + {"xor", R2_XORPEN}, +}; + +/* + * line types + */ +stringint siLineTypes[] = { + {0, 6}, + {"dashdotted", PS_DASHDOT}, + {"dashdotdotted", PS_DASHDOTDOT}, + {"dashed", PS_DOT}, + {"longdashed", PS_DASH}, + {"solid", PS_SOLID}, + {"striped", PS_DOT} +}; + +HINSTANCE mswinInstance; +int ncmdShow; + +int FoundIt, FoundNew; +HWND NewWin; +char *lookingfor; +struct WNDlist { + HWND w; + struct WNDlist *next; + } * wlhead; + +struct WNDlist *wlinsert(HWND w) +{ + struct WNDlist *x = malloc(sizeof (struct WNDlist)); + x->w = w; + x->next = wlhead; + wlhead = x; +} + +int wlsearch(HWND w) +{ + struct WNDlist *x; + for(x=wlhead;x;x=x->next) if (x->w == w) return 1; + return 0; +} + +void wlfree() +{ + struct WNDlist *x = wlhead; + while (wlhead) { + x = wlhead->next; + free(wlhead); + wlhead = x; + } +} + +BOOL_CALLBACK myenumproc(HWND w, LPARAM l) +{ + wlinsert(w); + return 1; +} + +BOOL_CALLBACK myenumproc2(HWND w, LPARAM l) +{ + if (!wlsearch(w)) { + FoundNew++; + NewWin = w; + } + return 1; +} + +char * strcasestr(char *haystack, char *needle) +{ + int len = strlen(needle); + while (*haystack) { + if (strncasecmp(haystack, needle, len) == 0) return haystack; + haystack++; + } + return 0; +} + +BOOL_CALLBACK myenumproc3(HWND w, LPARAM l) +{ + char s[64], s2[64]; + GetWindowText(w, s2, 63); + /* + * Conditions to find a window: + * 1) wasn't in the list of windows already present when we launched. + * 2) either contains the argv[0] program name, or + * was first window to appear after we called WinExec(). + */ + if (!wlsearch(w)) { + FoundNew++; + if ((strcasestr(s2, lookingfor) != NULL) || (NewWin && (NewWin == w))) { + FoundIt++; + } + } + return 1; +} + +char *lookcmdname(char *buf, char *s) +{ + char *t = buf; + while (*s) { + *t++ = *s; + if (*s == '\\') t = buf; + s++; + } + *t++ = '\0'; + s = buf; + while (*s) { + if (*s == '.') *s = '\0'; + s++; + } + return buf; +} + + +/* + * wopen + */ +FILE *wopen(char *name, struct b_list *lp, dptr attr, int n, int *err_idx) + { + wbp w; + wsp ws; + wcp wc; + struct imgdata *imd; + char answer[256]; + int i, r; + tended struct b_list *tlp; + tended struct descrip attrrslt; + HDC hdc, hdc2, hdc3; + TEXTMETRIC metrics; + LOGPALETTE logpal[4]; /* really 1 + space for an extra palette entry */ + HBRUSH brush; + HBITMAP oldpix, oldpix2; + HFONT oldfont; + + if (! winInitialized++) { + BORDWIDTH = FRAMEWIDTH * 2; + BORDHEIGHT = TITLEHEIGHT + FRAMEHEIGHT * 2 - 1; + GetCPInfo(CP_ACP, &cpinfo); + MAXBYTESPERCHAR = cpinfo.MaxCharSize; + } + + tlp = lp; + + /* + * allocate a binding, a window state, and a context + */ + Protect(w = alc_wbinding(), return NULL); + Protect(w->window = alc_winstate(), { free_binding(w); return NULL; }); + Protect(w->context = alc_context(w), { free_binding(w); return NULL; }); + ws = w->window; + ws->listp.dword = D_List; + BlkLoc(ws->listp) = (union block *)lp; + ws->width = ws->height = 0; + wc = w->context; + + /* + * process the passed in attributes - by calling wattrib + */ + for(i = 0; i < n; i++) + switch (wattrib(w, StrLoc(attr[i]), StrLen(attr[i]), &attrrslt, + answer)) { + case Failed: + wclose(w); + return NULL; + case Error: + /* think of something to do here */ + break; + } + + /* + * set the title, defaulting to the "filename" supplied to open() + */ + if (ws->windowlabel == NULL) ws->windowlabel = salloc(name); + if (ws->iconlabel == NULL) ws->iconlabel = salloc(name); + + if (ws->posx < 0) ws->posx = 0; + if (ws->posy < 0) ws->posy = 0; + + /* + * create the window + */ + ws->iconwin = CreateWindow( "iconx", ws->windowlabel, WS_OVERLAPPEDWINDOW, + ws->posx, ws->posy, + ws->width == 0 ? 400 : ws->width + BORDWIDTH, + ws->height == 0 ? 400: ws->height + BORDHEIGHT, + NULL, NULL, mswinInstance, NULL); + hdc = GetDC(ws->iconwin); + if ((GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) && (numColors == 0)){ + /* This window is on a device that supports palettes */ + numColors = 2; + logpal[0].palNumEntries = 2; + logpal[0].palVersion = 0x300; + logpal[0].palPalEntry[0].peFlags = 0; + logpal[0].palPalEntry[0].peRed = 0; + logpal[0].palPalEntry[0].peGreen = 0; + logpal[0].palPalEntry[0].peBlue = 0; + logpal[0].palPalEntry[1].peFlags = 0; + logpal[0].palPalEntry[1].peRed = 255; + logpal[0].palPalEntry[1].peGreen = 255; + logpal[0].palPalEntry[1].peBlue = 255; + palette = CreatePalette(logpal); + if ((scp = malloc(2 * sizeof (struct wcolor))) == NULL) return NULL; + scp[0].c = RGB(0,0,0); + scp[0].type = SHARED; + strcpy(scp[0].name, "black"); + scp[1].c = RGB(255,255,255); + scp[1].type = SHARED; + strcpy(scp[1].name, "white"); + } + oldfont = SelectObject(hdc, wc->font->font); + GetTextMetrics(hdc, &metrics); + wc->font->charwidth = dc_maxcharwidth(hdc); + SelectObject(hdc, oldfont); + ReleaseDC(ws->iconwin, hdc); + wc->font->ascent = metrics.tmAscent; + wc->font->descent = metrics.tmDescent; + /* wc->font->charwidth = metrics.tmMaxCharWidth; buggy */ + wc->font->height = metrics.tmHeight; + wc->leading = metrics.tmHeight; + ws->x = 0; + ws->y = ASCENT(w); + ws->y += w->context->dy; + ws->x += w->context->dx; + /* + * set the generic window's true default sizes + */ + if (!ws->width || !ws->height) { + if (!ws->width) ws->width = FWIDTH(w) * 80; + if (!ws->height) ws->height = FHEIGHT(w) * 12; + SetWindowPos(ws->iconwin, ws->iconwin, + ws->posx, + ws->posy, + ws->width + BORDWIDTH, ws->height + BORDHEIGHT, + SWP_NOZORDER); + } + if (!ws->pix) { + hdc = GetDC(ws->iconwin); + ws->pix = CreateCompatibleBitmap(hdc, ws->width, ws->height); + ReleaseDC(ws->iconwin, hdc); + } + + if (alc_rgb(w, wc->fg) == Failed) { + return 0; + } + if (alc_rgb(w, wc->bg) == Failed) { + return 0; + } + ws->pixwidth = ws->width; + ws->pixheight = ws->height; + if (!ISTOBEHIDDEN(ws)) { + ws->win = ws->iconwin; + ShowWindow(ws->win, ncmdShow); + } + else ws->win = 0; + + if (ws->initialPix) { + hdc = GetDC(ws->iconwin); + hdc2 = CreateCompatibleDC(hdc); + oldpix = SelectObject(hdc2, ws->pix); + hdc3 = CreateCompatibleDC(hdc); + oldpix2 = SelectObject(hdc3, ws->initialPix); + BitBlt(hdc2, 0, 0, ws->width, ws->height, hdc3, 0, 0, SRCCOPY); + if (ws->win) + BitBlt(hdc, 0, 0, ws->width, ws->height, hdc3, 0, 0, SRCCOPY); + SelectObject(hdc2, oldpix); + SelectObject(hdc3, oldpix2); + DeleteDC(hdc2); + DeleteDC(hdc3); + DeleteObject(ws->initialPix); + ws->initialPix = (HBITMAP) NULL; + } + else { + /* + * initialize the image with the background color + */ + RECT rec; + hdc = GetDC(ws->iconwin); + hdc2 = CreateCompatibleDC(hdc); + oldpix = SelectObject(hdc2, ws->pix); + rec.left = rec.top = 0; + rec.right = ws->width; + rec.bottom = ws->height; + if (palette) { + SelectPalette(hdc, palette, FALSE); + SelectPalette(hdc2, palette, FALSE); + RealizePalette(hdc); + RealizePalette(hdc2); + } + brush = CreateBrushIndirect(&(wc->bgbrush)); + if (ws->win) + FillRect(hdc, &rec, brush); + FillRect(hdc2, &rec, brush); + DeleteObject(brush); + SelectObject(hdc2, oldpix); + ReleaseDC(ws->iconwin, hdc); + DeleteDC(hdc2); + + imd = &ws->initimage; + if (imd->width) { + r = strimage(w, 0, 0, imd->width, imd->height, imd->paltbl, + imd->data, (word)imd->width * (word)imd->height, 0); + free((pointer)imd->paltbl); + free((pointer)imd->data); + imd->width = 0; + if (r < 0) { + return 0; + } + } + } + if (ws->win) + UpdateWindow(ws->win); + + return (FILE *)w; + } + +int handle_config(wbp w, UINT msg, WPARAM wp, LPARAM lp) + { + int neww, newh; + struct descrip d; + wsp ws = w->window; + + if (wp == SIZE_MINIMIZED) { + if (ws->win) { + SetWindowText(ws->win, ws->iconlabel); + ws->win = NULL; + } + return 1; + } + + if (ws->win) + SetWindowText(ws->win, ws->windowlabel); + ws->win = ws->iconwin; + + /* + * make sure text cursor stays on-screen + */ + ws->x = min(ws->x, LOWORD(lp) - FWIDTH(w)); + ws->y = min(ws->y, HIWORD(lp)); + + neww = LOWORD(lp); + newh = HIWORD(lp); + + /* + * if it was not a resize, drop it + */ + if ((ws->width == neww) && (ws->height == newh)) { + return 1; + } + + ws->width = neww; + ws->height = newh; + if (! resizePixmap(w, ws->width, ws->height)) return 0; + if (!ISEXPOSED(w)) { + SETEXPOSED(w); + return 1; + } + MakeInt(RESIZED, &d); + qevent(w->window, &d, ws->width, ws->height, ~(uword)0, 0); + return 1; + } + +/* + * handle window controls (child windows), at the moment these are + * buttons and scrollbars. wp is which child (base 1). + * Buttons come in as undiluted messages. + * Scrollbars come in with msg = new value of scrollbar + */ +void handle_child(wbp wb, UINT msg, WPARAM wp, LPARAM lp) + { + DWORD dw; + LONG t; + WORD x, y; + wsp ws = wb->window; + char *s; + int len; + struct descrip d; + int flags = 0; + if (LOWORD(wp) > ws->nChildren) return; + s = ws->child[LOWORD(wp) - 1].id; + len = strlen(s); + d = nulldesc; + StrLoc(d) = alcstr(s, len); + StrLen(d) = len; + switch (HIWORD(wp)) { + case BN_CLICKED: { + dw = GetMessagePos(); + x = LOWORD(dw); + y = HIWORD(dw); + break; + } + case EN_SETFOCUS: case EN_KILLFOCUS: case EN_CHANGE: case EN_UPDATE: + case EN_ERRSPACE: case EN_MAXTEXT: case EN_HSCROLL: case EN_VSCROLL: { + return; + } + default: { /* scrollbar */ + x = y = msg; + } + } + t = GetMessageTime(); + qevent(ws, &d, x, y, t, flags); + if (ws->focusChild) + SetFocus(ws->focusChild); + else if (ws->win) + SetFocus(ws->win); + else + SetFocus(ws->iconwin); + } + +void handle_menu(wbp wb, UINT msg, WPARAM wp, LPARAM lp) + { + wsp ws = wb->window; + DWORD dw; + LONG t; + WORD x, y; + struct descrip d; + char *s = ws->menuMap[wp]; + int len = strlen(s); + int flags = 0; + + d = nulldesc; + StrLoc(d) = alcstr(s, len); + StrLen(d) = len; + dw = GetMessagePos(); + x = LOWORD(dw); + y = HIWORD(dw); + t = GetMessageTime(); + qevent(ws, &d, x, y, t, flags); + } + +void handle_keypress(wbp wb, UINT msg, WPARAM wp, LPARAM lp, int meta) + { + wsp ws = wb->window; + DWORD dw; + LONG t; + WORD x, y; + struct descrip d; + int flags = 0; + if (msg == WM_CHAR || msg == WM_SYSCHAR) { + StrLen(d) = 1; + StrLoc(d) = (char *)&allchars[wp & 0xFF]; + } + else { /* WM_KEYDOWN or WM_SYSKEYDOWN */ + MakeInt(wp, &d); + } + dw = GetMessagePos(); + x = LOWORD(dw); + y = HIWORD(dw); + t = GetMessageTime(); + if (GetKeyState(VK_CONTROL) < 0) flags |= ControlMask; + if (GetKeyState(VK_SHIFT) < 0) flags |= ShiftMask; + + if (meta) flags |= Mod1Mask; + qevent(ws, &d, x, y, t, flags); + } + +void handle_mouse(wbp wb, UINT msg, WPARAM wp, LPARAM lp) + { + wsp ws = wb->window; + LONG t; + WORD x, y; + struct descrip d; + long flags = 0, eventcode; + + switch(msg) { + case WM_MOUSEMOVE: /* only called if one of these three cases is true */ + if (MK_LBUTTON & wp) + eventcode = MOUSELEFTDRAG; + else if (MK_RBUTTON & wp) + eventcode = MOUSERIGHTDRAG; + else if (MK_MBUTTON & wp) + eventcode = MOUSEMIDDRAG; + else eventcode = 0; + break; + case WM_LBUTTONDOWN: + eventcode = MOUSELEFT; + break; + case WM_MBUTTONDOWN: + eventcode = MOUSEMID; + break; + case WM_RBUTTONDOWN: + eventcode = MOUSERIGHT; + break; + case WM_LBUTTONUP: + eventcode = MOUSELEFTUP; + break; + case WM_MBUTTONUP: + eventcode = MOUSEMIDUP; + break; + case WM_RBUTTONUP: + eventcode = MOUSERIGHTUP; + break; + default: + eventcode = 0; + break; + } + + MakeInt(eventcode, &d); + x = LOWORD(lp); + y = HIWORD(lp); + t = GetMessageTime(); /* why might someone comment this out? */ + + if (MK_CONTROL & wp) flags |= ControlMask; + if (MK_SHIFT & wp) flags |= ShiftMask; + + qevent(ws, &d, x, y, t, flags); + } + +LRESULT_CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) +{ + HDC hdc, hdc2; + PAINTSTRUCT ps; + RECT rect; + wbp wb = NULL; + wsp ws = NULL; + int n, i, imin, imax; + + /* + * find a binding associated with the given window. + */ + for (wb = wbndngs; wb; wb=wb->next) { + ws = wb->window; + + if ((ws->win == hwnd) || (ws->iconwin == hwnd)) break; + } + if (msg == WM_QUIT) { + wfreersc(); + } + else if (!wb) { + /* + * doesn't look like its for one of our windows, pass it to + * DefWindowProc and hope for the best. + */ + } + else + switch(msg) { + case WM_PAINT: + hdc = BeginPaint(hwnd, &ps); + GetClientRect(hwnd, &rect); + if (IsIconic(hwnd)) { + HBRUSH hb = CreateBrushIndirect(&(wb->context->brush)); + FrameRect(hdc, &rect, hb); + DeleteObject(hb); + DrawText(hdc, "Iconx", 5, &rect, DT_WORDBREAK); + } + else { + HBITMAP oldpix; + hdc2 = CreateCompatibleDC(hdc); + oldpix = SelectObject(hdc2, ws->pix); + BitBlt(hdc, rect.left, rect.top, + rect.right - rect.left + 1, rect.bottom - rect.top + 1, + hdc2, rect.left, rect.top, SRCCOPY); + SelectObject(hdc2, oldpix); + DeleteDC(hdc2); + } + EndPaint(hwnd, &ps); + return 0; + case WM_MOUSEMOVE: + if (ws->curcursor) + SetCursor(ws->curcursor); + if ((MK_LBUTTON | MK_RBUTTON | MK_MBUTTON) & wp) + handle_mouse(wb,msg,wp,lp); + return 0; + case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: + case WM_LBUTTONUP: case WM_RBUTTONUP: case WM_MBUTTONUP: + handle_mouse(wb,msg,wp,lp); + return 0; + case WM_KEYDOWN: + switch (wp) { /* VK defn's from <winuser.h> */ + case VK_F1: case VK_F2: case VK_F3: case VK_F4: + case VK_F5: case VK_F6: case VK_F7: case VK_F8: + case VK_F9: case VK_F10: case VK_F11: case VK_F12: + case VK_HOME: case VK_END: case VK_PRIOR: case VK_NEXT: + case VK_LEFT: case VK_RIGHT: case VK_UP: case VK_DOWN: + case VK_INSERT: case VK_SELECT: case VK_PRINT: + case VK_EXECUTE: case VK_SNAPSHOT: case VK_HELP: case VK_SEPARATOR: + case VK_CLEAR: case VK_PAUSE: case VK_SCROLL: + handle_keypress(wb, msg, wp, lp, 0); + return 0; + case VK_DELETE: + handle_keypress(wb, WM_CHAR, '\177', lp, 0); + return 0; + } + break; + case WM_SYSKEYDOWN: + switch (wp) { + case VK_F1: case VK_F2: case VK_F3: /* alt-F4 terminates */ + case VK_F5: case VK_F6: case VK_F7: case VK_F8: + case VK_F9: case VK_F10: case VK_F11: case VK_F12: + case VK_HOME: case VK_END: case VK_PRIOR: case VK_NEXT: + case VK_LEFT: case VK_RIGHT: case VK_UP: case VK_DOWN: + case VK_INSERT: case VK_DELETE: case VK_SELECT: case VK_PRINT: + case VK_EXECUTE: case VK_SNAPSHOT: case VK_HELP: case VK_SEPARATOR: + case VK_CLEAR: case VK_PAUSE: + handle_keypress(wb, msg, wp, lp, 1); + return 0; + } + break; + case WM_CHAR: + handle_keypress(wb, msg, wp, lp, 0); + return 0; + case WM_SYSCHAR: + handle_keypress(wb, msg, wp, lp, 1); + /* + * Unless there is a menu bar installed, + * Alt-A .. Alt-Z, and Alt-0 .. Alt-9 are eaten by Icon; + * others are passed on to Windows for things like Alt-Esc. + */ + if (isalnum(wp) && !(ws->menuMap)) return 0; + break; + case WM_HSCROLL: + case WM_VSCROLL: + for(n=0; n < ws->nChildren && ws->child[n].win != (HWND)lp; n++){ + } + if (n == ws->nChildren) break; + i = GetScrollPos(ws->child[n].win, SB_CTL); + GetScrollRange(ws->child[n].win, SB_CTL, &imin, &imax); + switch (LOWORD(wp)) { + case SB_PAGEDOWN : + break; + case SB_LINEDOWN : + if (i < imax) { + SetScrollPos(ws->child[n].win, SB_CTL, + GetScrollPos(ws->child[n].win, SB_CTL) + 1, TRUE); + } + break; + case SB_PAGEUP : + break; + case SB_LINEUP : + if (i > imin) { + SetScrollPos(ws->child[n].win, SB_CTL, + GetScrollPos(ws->child[n].win, SB_CTL) - 1, TRUE); + } + break; + case SB_TOP : + SetScrollPos(ws->child[n].win, SB_CTL, imin, TRUE); + break; + case SB_BOTTOM : + SetScrollPos(ws->child[n].win, SB_CTL, imax, TRUE); + break; + case SB_THUMBPOSITION : + SetScrollPos(ws->child[n].win, SB_CTL, HIWORD(wp), TRUE); + break; + case SB_THUMBTRACK : + SetScrollPos(ws->child[n].win, SB_CTL, HIWORD(wp), TRUE); + break; + case SB_ENDSCROLL: /* noop */ + break; + default : /* potentially a problem here */ + break; + } + i = GetScrollPos(ws->child[n].win, SB_CTL); + handle_child(wb, i, n+1, -1); + break; + case WM_COMMAND: + if (LOWORD(lp) == 0) + handle_menu(wb, msg, wp, lp); + else + handle_child(wb, msg, wp, lp); + break; + case WM_SIZE: + handle_config(wb, msg, wp, lp); + break; + case WM_MOVE: + ws->posx = LOWORD(lp) - (BORDWIDTH>>1); + ws->posy = HIWORD(lp) - (BORDHEIGHT - 4); + break; + case WM_ACTIVATE: + if (wp == WA_INACTIVE) { + if (ws->savedcursor) SetCursor(ws->savedcursor); + if (ws->hasCaret) { + HideCaret(ws->iconwin); + DestroyCaret(); + ws->hasCaret = 0; + } + } + else { /* ... */ + if (ws->savedcursor == NULL) + ws->savedcursor = SetCursor(ws->curcursor); + else (void) SetCursor(ws->curcursor); + if (ISCURSORON(wb)) { + CreateCaret(ws->iconwin, NULL, FWIDTH(wb), FHEIGHT(wb)); + SetCaretPos(ws->x, ws->y - ASCENT(wb)); + SetCaretBlinkTime(500); + ShowCaret(ws->iconwin); + ws->hasCaret = 1; + } + } + break; + case WM_GETMINMAXINFO: { + MINMAXINFO *mmi = (MINMAXINFO *)lp; + if (! ISRESIZABLE(wb)) { + mmi->ptMinTrackSize.x = mmi->ptMaxTrackSize.x = + ws->width + BORDWIDTH; + mmi->ptMinTrackSize.y = mmi->ptMaxTrackSize.y = + ws->height + BORDHEIGHT; + } + return 0; + } + case WM_KILLFOCUS: + if (ws->hasCaret) { + HideCaret(ws->iconwin); + DestroyCaret(); + ws->hasCaret = 0; + } + break; + case WM_SETFOCUS: + if (ws->focusChild) + SetFocus(ws->focusChild); + else if (ISCURSORON(wb)) { + CreateCaret(ws->iconwin, NULL, FWIDTH(wb), FHEIGHT(wb)); + SetCaretPos(ws->x, ws->y - ASCENT(wb)); + SetCaretBlinkTime(500); + ShowCaret(ws->iconwin); + ws->hasCaret = 1; + } + break; + /* case WM_QUIT is handled prior to the switch*/ + case WM_DESTROY: + if (ws->win == hwnd) + ws->win = NULL; + if (ws->iconwin == hwnd) + ws->iconwin = NULL; + if (ws->refcount > 0) { + PostQuitMessage(0); + return 0; + } + else if (ws->refcount < 0) { + ws->refcount = -ws->refcount; + } + break; + case MM_MCINOTIFY: + mciSendCommand(LOWORD(lp), MCI_CLOSE, 0, (DWORD)NULL); + break; + } + return DefWindowProc(hwnd, msg, wp, lp); +} + +/* + * wclose - make sure the window goes away - no questions asked + */ +int wclose(wbp w) + { + wsp ws = w->window; + if (pollevent() == -1) return -1; + if (ws->win && ws->refcount > 1) { + /* + * Decrement refcount and negate it to tell the window procedure + * that we closed the window, not the user, so don't terminate. + */ + ws->refcount--; + ws->refcount = -ws->refcount; + DestroyWindow(ws->win); + while (ws->win) + if (pollevent() == -1) return -1; + } + else { + free_binding(w); + } + return 1; + } + +int pollevent() + { + wbp w; + MSG m; + int result; + + /* some while PeekMessage loops here, maybe one per window ? */ + while (PeekMessage(&m, NULL, 0, 0, PM_NOREMOVE)) { + if ((result = check_and_get_msg(&m)) <= 0) return result; + TranslateMessage(&m); + DispatchMessage(&m); + } + return 400; + } + +/* + * write some text to both the window and the pixmap + */ +void xdis(w,s,n) +register wbp w; +char *s; +int n; + { + XPoint pt; + HBRUSH hb; + XRectangle rect; + STDLOCALS(w); + + STDFONT; + rect.left = ws->x; rect.right = ws->x + dc_textwidth(pixdc, s, n); + rect.top = ws->y - ASCENT(w); rect.bottom = ws->y + DESCENT(w); + + /* skip resource allocation if we are offscreen */ + if (!(rect.left > ws->width || rect.right < 0 || + rect.top < 0 || rect.bottom > ws->height)) { + + hb = CreateBrushIndirect(&(wc->bgbrush)); + if (stdwin) { + /* + * SetBkColor() does not dither consistently with bgbrush; + * erase the background beforehand and use transparent drawing + */ + FillRect(stddc, &rect, hb); + SetBkMode(stddc, TRANSPARENT); + SetTextColor(stddc, PALCLR(wc->fg)); + TextOut(stddc, ws->x, ws->y - ASCENT(w), s, n); + } + FillRect(pixdc, &rect, hb); + DeleteObject(hb); + SetBkMode(pixdc, TRANSPARENT); + SetTextColor(pixdc, PALCLR(wc->fg)); + TextOut(pixdc, ws->x, ws->y - ASCENT(w), s, n); + } + ws->x += dc_textwidth(pixdc, s, n); + + FREE_STDLOCALS(w); + } +/* + * wputc + */ +int wputc(int ci, wbp w) + { + char c = (char)ci; + wsp ws = w->window; + wcp wc = w->context; + int y_plus_descent; + HBRUSH hb; + + switch (c) { + case '\n': + ws->y += LEADING(w); + if (ws->y + DESCENT(w) > ws->height) { + RECT r; + STDLOCALS(w); + ws->y -= LEADING(w); + y_plus_descent = ws->y + DESCENT(w); + BitBlt(pixdc, 0, 0, + ws->width, y_plus_descent, + pixdc, 0, LEADING(w), SRCCOPY); + r.left = 0; + r.top = y_plus_descent - FHEIGHT(w); + r.right = ws->width; + r.bottom = ws->height; + hb = CreateBrushIndirect(&(wc->bgbrush)); + FillRect(pixdc, &r, hb); + DeleteObject(hb); + if (stdwin) + BitBlt(stddc, 0, 0, ws->width, ws->height, + pixdc, 0, 0, SRCCOPY); + FREE_STDLOCALS(w); + } + /* intended fall-through */ + case '\r': + /* + * set the new x position + */ + ws->x = wc->dx; + break; + case '\t': + xdis(w, " ", 8 - (XTOCOL(w,ws->x) & 7)); + break; + /* + * Handle backspaces. This implements cooked mode echo handling. + */ + case '\177': + case '\010': { + int i = 0, pre_x; + + /* + * Start with the last character queued up. + */ + i--; + /* + * Trot back to the control-H itself. + */ + while ((i>-EQUEUELEN) && (EVQUESUB(w,i) != c)) { + i--; + } + if (i == -EQUEUELEN) break; + /* + * Go past the control-H. + */ + i--; + /* + * Go back through any number of control-H's from prior lifetimes. + */ + while((i > -EQUEUELEN) && !isprint(EVQUESUB(w,i))) { + i--; + } + if (i == -EQUEUELEN) break; + + /* + * OK, here's the character we're actually rubbing out. Back up. + */ + c = EVQUESUB(w,i); + pre_x = ws->x; + ws->x -= TEXTWIDTH(w, &c, 1); + /* + * Physically erase the character from the queue. This results in + * two control-H's present in the queue. + */ + *evquesub(w,i) = '\010'; + /* + * Save the backed-up position, and draw spaces through the erased. + */ + i = ws->x; + while(ws->x < pre_x) { + xdis(w, " ",1); + } + ws->x = i; + break; + } + /* + * bell (control-G) + */ + case '\007': + break; + default: + xdis(w, &c, 1); + } + /* + * turn the cursor back on + */ + UpdateCursorPos(ws,wc); + return 0; + } + +/* + * wgetq - get event from pending queue + */ +int wgetq(wbp w, dptr res) + { + MSG m; + wsp ws; + int first = 0, i = 0, j; + int hascaret = 0; + FILE *f; + + if (!w || !(ws = w->window) || !(ws->iconwin)) { + return -1; + } + while (1) { + /* + * grab the built up queue + */ + if (!EVQUEEMPTY(ws)) { + EVQUEGET(ws, *res); + if (ws->hasCaret) { + HideCaret(ws->iconwin); + DestroyCaret(); + ws->hasCaret = 0; + } + return 1; + } + if (ISCURSORON(w) && ws->hasCaret == 0) { + CreateCaret(ws->iconwin, NULL, FWIDTH(w), FHEIGHT(w)); + SetCaretPos(ws->x, ws->y - ASCENT(w)); + SetCaretBlinkTime(500); + ShowCaret(ws->iconwin); + ws->hasCaret = 1; + } + i++; + if (check_and_get_msg(&m) <= 0) return -1; + TranslateMessage(&m); + DispatchMessage(&m); + } + } + +/* + * determine the new size of the client + */ +int setheight(w, height) +wbp w; +int height; + { + wsp ws = w->window; + ws->height = height; + return Succeeded; + } + +/* + * determine new size of client + */ +int setwidth(w, width) +wbp w; +SHORT width; + { + wsp ws = w->window; + ws->width = width; + return Succeeded; + } + +int setgeometry(w, geo) +wbp w; +char *geo; + { + wsp ws = w->window; + int width = 0, height = 0; + int x = 0, y = 0, status; + if ((status = parsegeometry(geo, &x, &y, &width, &height)) == 0) + return Error; + if (status & 1) { + ws->width = width; + ws->height = height; + } + if (status & 2) { + ws->posx = x; + ws->posy = y; + } + return Succeeded; + } + +int setcanvas(w,s) +wbp w; +char *s; + { + int cmd; + wsp ws = w->window; + HWND stdwin = ws->win; + + if (!strcmp(s, "iconic")) { + cmd = SW_MINIMIZE; + CLRTOBEHIDDEN(ws); + } + else if (!strcmp(s, "normal")) { + cmd = SW_RESTORE; + stdwin = ws->win = ws->iconwin; + CLRTOBEHIDDEN(ws); + } + else if (!strcmp(s, "maximal")) { + cmd = SW_SHOWMAXIMIZED; + stdwin = ws->win = ws->iconwin; + CLRTOBEHIDDEN(ws); + } + else if (!strcmp(s, "hidden")) { + cmd = SW_HIDE; + SETTOBEHIDDEN(ws); + } + else { + return Error; + } + if (stdwin) + ShowWindow(stdwin, cmd); + + return Succeeded; + } + +int seticonicstate(w, val) +wbp w; +char *val; + { + int height; + return Failed; + } + +int seticonlabel(w, val) +wbp w; +char *val; + { + wsp ws = w->window; + if (ws->iconlabel != NULL) free(ws->iconlabel); + ws->iconlabel = salloc(val); + if (ws->win && IsIconic(ws->win)) + SetWindowText(ws->win, ws->iconlabel); + return Succeeded; + } + +int seticonpos(w, val) +wbp w; +char *val; + { + return Failed; + } + + +int setwindowlabel(w, val) +wbp w; +char *val; + { + wsp ws = w->window; + /* + * plug in the new string + */ + if (ws->windowlabel != NULL) + free(ws->windowlabel); + ws->windowlabel = salloc(val); + + /* + * if we have to update, do it + */ + if (ws->win && !IsIconic(ws->win)) + SetWindowText(ws->win, ws->windowlabel); + return Succeeded; + } + +int setcursor(w, on) +wbp w; +int on; + { + wsp ws = w->window; + if (on) { + SETCURSORON(w); + } + else { + CLRCURSORON(w); + } + return Succeeded; + } + +HFONT findfont(char *family, int size, int flags, int ansi) +{ + int weight; + char slant, spacing; + + if (size < 0) size = DEFAULTFONTSIZE; + + if (flags & FONTFLAG_MEDIUM) + weight = FW_MEDIUM; + else if ((flags & FONTFLAG_DEMI) && (flags & FONTFLAG_BOLD)) + weight = FW_DEMIBOLD; + else if (flags & FONTFLAG_BOLD) + weight = FW_BOLD; + else if (flags & FONTFLAG_DEMI) + weight = FW_SEMIBOLD; + else if (flags & FONTFLAG_LIGHT) + weight = FW_LIGHT; + else + weight = FW_DONTCARE; + + if (flags & FONTFLAG_ITALIC) + slant = 1; + else + slant = 0; + + if (flags & FONTFLAG_PROPORTIONAL) + spacing = VARIABLE_PITCH; + else if (flags & FONTFLAG_MONO) + spacing = FIXED_PITCH; + else spacing = DEFAULT_PITCH; + + return CreateFont(size, 0, 0, 0, weight, slant, 0, 0, + (ansi && (MAXBYTESPERCHAR==1)) ? ANSI_CHARSET:DEFAULT_CHARSET, + OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, + spacing, family); +} + +HFONT mkfont(char *s) +{ + int flags, size; + char family[MAXFONTWORD+1]; + char *stdfam = NULL; + HFONT hf = 0; + + if (parsefont(s, family, &flags, &size)) { + /* + * This is a legal Icon font spec. + * Check first for special "standard" family names. + */ + if (!strcmp(family, "mono") || !strcmp(family, "fixed")) { + stdfam = "Lucida Sans"; + flags |= FONTFLAG_MONO + FONTFLAG_SANS; + } + else if (!strcmp(family, "typewriter")) { + stdfam = "Courier New"; /* was "courier" */ + flags |= FONTFLAG_MONO + FONTFLAG_SERIF; + } + else if (!strcmp(family, "sans")) { + stdfam = "Arial"; /* was "swiss" */ + flags |= FONTFLAG_PROPORTIONAL + FONTFLAG_SANS; + } + else if (!strcmp(family, "serif")) { + stdfam = "Times New Roman"; + flags |= FONTFLAG_PROPORTIONAL + FONTFLAG_SERIF; + } + else stdfam = NULL; + + if (stdfam) { + /* + * Standard name: first try preferred family, then generalize. + * ICONFONT can be NULL, in which case Windows chooses. + */ + hf = findfont(stdfam, size, flags, 1); + if (hf == NULL) + hf = findfont(getenv("ICONFONT"), size, flags, 1); + } + else { + /* + * Any other name: must match as specified. + */ + hf = findfont(family, size, flags, 0); + } + } + return hf; +} + +/* + * Set the window's font by name. + */ +int setfont(w, s) +wbp w; +char **s; + { + wsp ws = w->window; + wcp wc = w->context; + HFONT hf, oldfont; + TEXTMETRIC metrics; + HDC tmpdc; + + hf = mkfont(*s); + if (hf != NULL) { + if (wc->font->font) + DeleteObject(wc->font->font); + wc->font->font = hf; + if (wc->font->name) + free(wc->font->name); + wc->font->name = salloc(*s); + + tmpdc = GetDC(ws->iconwin); + oldfont = SelectObject(tmpdc, hf); + wc->font->charwidth = dc_maxcharwidth(tmpdc); + if (GetTextMetrics(tmpdc, &metrics) == 0) { + /* gettextmetrics can fail; what should we do about it? */ + ; + } + SelectObject(tmpdc, oldfont); + ReleaseDC(ws->iconwin, tmpdc); + wc->font->ascent = metrics.tmAscent; + wc->font->descent = metrics.tmDescent; +/* wc->font->charwidth = metrics.tmMaxCharWidth; unreliable due to MS bug */ + wc->leading = wc->font->height = metrics.tmHeight; + return Succeeded; + } + return Failed; + } + +/* + * rebind() - bind w's context to that of w2. + */ +int rebind(w, w2) +wbp w, w2; + { + wsp ws = w->window; + /* decrement w->context->refcount? increment w2->context->refcount? */ + w->context = w2->context; + return Succeeded; + } + +void setclip(w) +wbp w; + { + wcp wc = w->context; + if (wc->cliprgn) + DeleteObject(wc->cliprgn); + if (wc->clipw >= 0) + wc->cliprgn = CreateRectRgn(wc->clipx, wc->clipy, + wc->clipx + wc->clipw, + wc->clipy + wc->cliph); + else + wc->cliprgn = NULL; + } + +void unsetclip(w) +wbp w; + { + wcp wc = w->context; + if (wc->cliprgn) + DeleteObject(wc->cliprgn); + wc->cliprgn = NULL; + } + + int lowerWindow(wbp w) + { + wsp ws = w->window; + if (ws->win) + SetWindowPos(ws->win, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + return Succeeded; + } + +int raiseWindow(wbp w) + { + wsp ws = w->window; + if (ws->win) + SetWindowPos(ws->win, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + return Succeeded; + } + +int nativecolor(w, s, r, g, b) +wbp w; +char *s; +long *r, *g, *b; + { + return 0; /* no new colors beyond those of Icon */ + } +/* + * convert an Icon linear color into an MS Windows color value + */ +SysColor mscolor(wbp w, long r, long g, long b) +{ + SysColor x; + double invgamma = 1.0 / w->context->gamma; + long int red, green, blue; + + red = 65535L * pow(r / 65535.0, invgamma); + green = 65535L * pow(g / 65535.0, invgamma); + blue = 65535L * pow(b / 65535.0, invgamma); + return RGB(red >> 8, green >> 8, blue >> 8); +} + +/* + * Set the context's fill style by name. + */ +int setfillstyle(w, s) +wbp w; +char *s; + { + wcp wc = w->context; + + if (!strcmp(s, "solid")) { + wc->brush.lbStyle = wc->fillstyle = BS_SOLID; + wc->brush.lbColor = PALCLR(wc->fg); + } + else { + if (!strcmp(s, "masked") + || !strcmp(s, "stippled") || !strcmp(s, "patterned")) { + wc->brush.lbStyle = wc->fillstyle = BS_PATTERN; + wc->brush.lbColor = PALCLR(wc->fg); + wc->brush.lbHatch = (LONG)wc->pattern; + wc->bkmode = TRANSPARENT; + } + else if (!strcmp(s, "textured") + || !strcmp(s, "opaquestippled") || !strcmp(s, "opaquepatterned")) { + wc->brush.lbStyle = wc->fillstyle = BS_PATTERN; + wc->brush.lbColor = PALCLR(wc->fg); + wc->brush.lbHatch = (LONG)wc->pattern; + wc->bkmode = OPAQUE; + } + else { + return Error; + } + } + return Succeeded; + } + +/* + * Set the context's line style by name. + */ +int setlinestyle(w, s) +wbp w; +char *s; + { + wcp wc = w->context; + SHORT ltype; + + if ((ltype = si_s2i(siLineTypes, s)) < 0) + return Error; + wc->pen.lopnStyle = ltype; + resetfg(w); + if(!strcmp(s, "striped")) wc->bkmode = OPAQUE; + else wc->bkmode = TRANSPARENT; + return Succeeded; + } + +/* + * Set the context's line width + */ +int setlinewidth(wbp w, LONG linewid) + { + wcp wc = w->context; + wc->pen.lopnWidth.x = wc->pen.lopnWidth.y = + wc->bgpen.lopnWidth.x = wc->bgpen.lopnWidth.y = linewid; + return Succeeded; + } + + +/* + * Set the foreground to draw in a mutable color + */ +int isetfg(wbp w, int i) + { + char tmp[20]; + wcp wc = w->context; + if (-i > numColors) return Failed; + wc->fg = (0x01000000L | -i); + sprintf(tmp, "%ld", -i); + if (wc->fgname != NULL) free(wc->fgname); + wc->fgname = salloc(tmp); + wc->pen.lopnColor = wc->fg; + wc->brush.lbStyle = BS_SOLID; + wc->brush.lbColor = wc->fg; + return Succeeded; + } + +/* + * Set the context's background color by color cell. + */ +int isetbg(w, i) +wbp w; +int i; + { + char tmp[20]; + wcp wc = w->context; + if (-i > numColors) return Failed; + wc->bg = (0x01000000L | -i); + sprintf(tmp, "%ld", -i); + if (wc->bgname != NULL) free(wc->bgname); + wc->bgname = salloc(tmp); + wc->bgpen.lopnColor = wc->bg; + wc->bgbrush.lbStyle = BS_SOLID; + wc->bgbrush.lbColor = wc->bg; + return ISXORREVERSE(w) ? resetfg(w) : Succeeded; + } + + +int getdepthDC(HDC dc) +{ + return GetDeviceCaps(dc, BITSPIXEL) * GetDeviceCaps(dc, PLANES); +} + +int getdepth(wbp w) +{ + int i, j; + STDLOCALS(w); + i = GetDeviceCaps(pixdc, BITSPIXEL); + j = GetDeviceCaps(pixdc, PLANES); + FREE_STDLOCALS(w); + return i * j; +} + +int devicecaps(wbp w, int i) +{ + int rv; + STDLOCALS(w); + rv = GetDeviceCaps(pixdc, i); + FREE_STDLOCALS(w); + return rv; +} + +/* + * Reset the context's foreground color to whatever it is supposed to be. + */ +int resetfg(w) +wbp w; + { + return setfg(w, w->context->fgname); + } + +int alc_rgb(wbp w, SysColor rgb) +{ + int i; + wsp ws = w->window; + HDC hdc; + PALETTEENTRY pe; + LOGPALETTE lp; + if (palette) { + for (i=0; i < numColors; i++) { + if (rgb == scp[i].c && scp[i].type == SHARED) break; + } + if (i == numColors) { + numColors++; + if (ResizePalette(palette, numColors) == 0) { + numColors--; + return Failed; + } + scp = realloc(scp, numColors * sizeof(struct wcolor)); + if (scp == NULL) { numColors--; return Failed; } + scp[numColors - 1].c = rgb; + scp[numColors - 1].type = SHARED; + sprintf(scp[numColors - 1].name, "%d,%d,%d", + RED(rgb), GREEN(rgb), BLUE(rgb)); + lp.palNumEntries = 1; + lp.palVersion = 0x300; + lp.palPalEntry[0].peFlags = 0; + lp.palPalEntry[0].peRed = RED(rgb); + lp.palPalEntry[0].peGreen = GREEN(rgb); + lp.palPalEntry[0].peBlue = BLUE(rgb); + SetPaletteEntries(palette, numColors - 1, 1, lp.palPalEntry); + hdc = GetDC(ws->iconwin); + SelectPalette(hdc, palette, FALSE); + RealizePalette(hdc); + ReleaseDC(ws->iconwin, hdc); + } + } + return Succeeded; +} + +/* + * Retrieve next message, returning 0 if WM_QUIT, -1 if there is an error. + */ +int check_and_get_msg( MSG *pMsg ) +{ + BOOL result; + if ((result = GetMessage(pMsg, NULL, 0, 0)) <= 0) + { + return (result < 0) ? -1 : 0; + } + return 1; +} + +/* + * Set the context's foreground color + */ +int setfg(wbp w, char *val) + { + long r, g, b; + wcp wc = w->context; + if (parsecolor(w, val, &r, &g, &b) == Succeeded) { + wc->fg = mscolor(w, r, g, b); + if (alc_rgb(w, wc->fg) == Failed) return Failed; + if (!wc->fgname) wc->fgname = salloc(val); + else if (strcmp(wc->fgname, val)) { + free(wc->fgname); + wc->fgname = salloc(val); + } + wc->brush.lbColor = + PALCLR(ISXORREVERSE(w) ? ((wc->fg ^ wc->bg) & 0x00FFFFFF) : wc->fg); + wc->pen.lopnColor = wc->brush.lbColor; + wc->brush.lbStyle = wc->fillstyle; + if (wc->fillstyle == BS_PATTERN) + wc->brush.lbHatch = (LONG)wc->pattern; + return Succeeded; + } + return Failed; + } + +/* + * Set the window context's background color + */ +int setbg(wbp w, char *val) + { + long r, g, b; + wcp wc = w->context; + if (parsecolor(w, val, &r, &g, &b) == Succeeded) { + wc->bg = mscolor(w, r, g, b); + if (alc_rgb(w, wc->bg) == Failed) return Failed; + if (!wc->bgname) wc->bgname = salloc(val); + else if (strcmp(wc->bgname, val)) { + free(wc->bgname); + wc->bgname = salloc(val); + } + wc->bgpen.lopnColor = PALCLR(wc->bg); + wc->bgbrush.lbStyle = BS_SOLID; + wc->bgbrush.lbColor = PALCLR(wc->bg); + return ISXORREVERSE(w) ? resetfg(w) : Succeeded; + } + return Failed; + } + +/* + * Set the gamma correction factor. + */ +int setgamma(w, gamma) +wbp w; +double gamma; + { + wcp wc = w->context; + wc->gamma = gamma; + setfg(w, wc->fgname); + setbg(w, wc->bgname); + return Succeeded; + } + +/* + * setpointer() - define a mouse pointer shape + */ +int setpointer(w, val) +wbp w; +char *val; + { + HCURSOR c; + char *cval; + if (!strcmp(val,"arrow")) cval = IDC_ARROW; + else if (!strcmp(val,"cross")) cval = IDC_CROSS; + else if (!strcmp(val,"ibeam")) cval = IDC_IBEAM; + else if (!strcmp(val,"uparrow")) cval = IDC_UPARROW; + else if (!strcmp(val,"wait")) cval = IDC_WAIT; + else if (!strcmp(val,"starting")) cval = IDC_APPSTARTING; + else if (!strcmp(val,"icon")) cval = IDC_ICON; + else if (!strcmp(val,"size")) cval = IDC_SIZE; + else if (!strcmp(val,"sizenesw")) cval = IDC_SIZENESW; + else if (!strcmp(val,"sizens")) cval = IDC_SIZENS; + else if (!strcmp(val,"sizenwse")) cval = IDC_SIZENWSE; + else if (!strcmp(val,"sizewe")) cval = IDC_SIZEWE; + else if (!strcmp(val,"no")) cval = IDC_NO; + else { + return Failed; + } + c = LoadCursor(NULL, cval); + if (c == NULL) { + return Failed; + } + w->window->curcursor = c; + if (w->window->cursorname) free(w->window->cursorname); + w->window->cursorname = salloc(val); + if (! w->window->savedcursor) + w->window->savedcursor = SetCursor(c); + else (void) SetCursor(c); + /* should restore savedcursor when pointer moves outside our window */ + return Succeeded; + } + +/* + * setdrawop() - set the drawing operation + */ +int setdrawop(w, val) +wbp w; +char *val; + { + wcp wc = w->context; + if (!strcmp(val,"reverse")) { + if (!ISXORREVERSE(w)) { + SETXORREVERSE(w); + wc->drawop = R2_XORPEN; + resetfg(w); + } + } + else { + if (ISXORREVERSE(w)) { + CLRXORREVERSE(w); + resetfg(w); + } + wc->drawop = si_s2i(drawops,val); + if (wc->drawop == -1) { wc->drawop = R2_COPYPEN; return Error; } + } + return Succeeded; + } + +setdisplay(wbp w, char *val) + { + if (strcmp(val, "MS Windows")) + return Failed; + return Succeeded; + } + +setimage(wbp w, char *val) + { + wsp ws = w->window; + int status; + ws->initialPix = loadimage(w, val, &(ws->width), &(ws->height), + 0, &status); + if (ws->initialPix == (HBITMAP) NULL) return Failed; + return Succeeded; + } + +setleading(w, i) +wbp w; +int i; + { + wcp wc = w->context; + wc->leading = i; + } + +void toggle_fgbg(w) +wbp w; + { + SysColor tmp; + LOGPEN tpen; + LOGBRUSH tbrush; + wcp wc = w->context; + tmp = wc->fg; + wc->fg = wc->bg; + wc->bg = tmp; + tpen = wc->pen; + wc->pen = wc->bgpen; + wc->bgpen = tpen; + tbrush = wc->brush; + wc->brush = wc->bgbrush; + wc->bgbrush = tbrush; + } + +int getvisual(w, answer) +wbp w; +char *answer; + { + return Failed; + } + +/* + * getpos() - update the window state's notion of its current position + */ +int getpos(w) +wbp w; + { + return Succeeded; + } + +void getfg(w, answer) +wbp w; +char *answer; + { + strcpy(answer, w->context->fgname); + } + +void getbg(w, answer) +wbp w; +char *answer; + { + strcpy(answer, w->context->bgname); + } + +void getlinestyle(w, answer) +wbp w; +char *answer; + { + wcp wc = w->context; + char *ptr = si_i2s(siLineTypes, wc->pen.lopnStyle); + if (ptr != NULL) { + strcpy(answer, ptr); + } + else strcpy(answer, "unknown"); + } + +void getfntnam(w, answer) +wbp w; +char *answer; + { + strcpy(answer, w->context->font->name); + } + +void getpointername(w, answer) +wbp w; +char *answer; + { + char *s; + wsp ws = w->window; + strcpy(answer, w->window->cursorname); + } + +void getdisplay(wbp w, char *answer) + { + strcpy(answer, "MS Windows"); + } + +void getdrawop(w, answer) +wbp w; +char *answer; + { + char *s; + if (ISXORREVERSE(w)) s = "reverse"; + else s = si_i2s(drawops, w->context->drawop); + if (s) sprintf(answer, "%s", s); + else strcpy(answer, "unknown"); + } + +void geticonic(w, answer) +wbp w; +char *answer; + { + getcanvas(w, answer); + } + +void getcanvas(w, answer) +wbp w; +char *answer; + { + wsp ws = w->window; + if (ws->iconwin) { + if (!IsWindowVisible(ws->iconwin)) sprintf(answer, "hidden"); + else if (IsIconic(ws->iconwin)) sprintf(answer, "iconic"); + else if (IsZoomed(ws->iconwin)) sprintf(answer, "maximal"); + else sprintf(answer,"normal"); + } + else sprintf(answer,"hidden"); + } + +int geticonpos(w, val) +wbp w; +char *val; + { + return Failed; + } + +/* + * erase an area + */ +void eraseArea(w,x,y,width,height) +wbp w; +int x, y, width, height; + { + HBRUSH hb, oldbrush, oldbrush2; + XRectangle rect; + STDLOCALS(w); + hb = CreateBrushIndirect(&(wc->bgbrush)); + if (stdwin) oldbrush = SelectObject(stddc, hb); + oldbrush2 = SelectObject(pixdc, hb); + rect.left = x; rect.right = x + width; + rect.top = y; rect.bottom = y + height; + + if (stdwin) FillRect(stddc, &rect, hb); + FillRect(pixdc, &rect, hb); + if (stdwin) SelectObject(stddc, oldbrush); + SelectObject(pixdc, oldbrush2); + DeleteObject(hb); + FREE_STDLOCALS(w); + } + +/* + * copy an area + */ +int copyArea(w,w2,x,y,width,height,x2,y2) +wbp w, w2; +int x, y, width, height, x2, y2; + { + int lpad, rpad, tpad, bpad; + RECT r; + HDC srcdc, srcpixdc; + HBRUSH hb; + wsp ws1 = w->window; + HBITMAP oldpix; + STDLOCALS(w2); + /* + * setup device contexts for area copy + */ + SetROP2(pixdc, R2_COPYPEN); + hb = CreateBrushIndirect(&(wc->bgbrush)); + if (stdwin) + SetROP2(stddc, R2_COPYPEN); + if (w2->window == w->window) { + srcdc = pixdc; + srcpixdc = pixdc; + } + else { + srcdc = GetDC(w->window->iconwin); + srcpixdc = CreateCompatibleDC(srcdc); + SetROP2(srcpixdc, R2_COPYPEN); + } + oldpix = SelectObject(srcpixdc, w->window->pix); + + /* + * copy area, write unavailable areas with bg color + */ + if (x + width < 0 || y + height < 0 || x >= ws1->pixwidth || y >= ws1->pixheight) { + /* source is entirely offscreen, just fill with background */ + r.left = x2; r.top = y2; + r.right = x2 + width; r.bottom = y2 + height; + if (stdwin) + FillRect(stddc, &r, hb); + FillRect(pixdc, &r, hb); + } + else { + /* + * Check for source partially offscreen, but copy first and + * fill later in case the source and destination overlap. + */ + lpad = rpad = tpad = bpad = 0; + if (x < 0) { /* source extends past left edge */ + lpad = -x; + width -= lpad; + x2 += lpad; + x = 0; + } + if (x + width > ws1->pixwidth) { /* source extends past right edge */ + rpad = x + width - ws1->pixwidth; + width -= rpad; + } + if (y < 0) { /* source extends above top edge */ + tpad = -y; + height -= tpad; + y2 += tpad; + y = 0; + } + if (y + height > ws1->pixheight) { /* source extends below bottom */ + bpad = y + height - ws1->pixheight; + height -= bpad; + } + if (stdwin) + BitBlt(stddc, x2, y2, width, height, srcpixdc, x, y, SRCCOPY); + BitBlt(pixdc, x2, y2, width, height, srcpixdc, x, y, SRCCOPY); + + if (lpad > 0) { + r.left = x2-lpad; + r.top = y2-tpad; + r.right = r.left + lpad; + r.bottom = r.top + tpad+height+bpad; + if (stdwin) + FillRect(stddc, &r, hb); + FillRect(pixdc, &r, hb); + } + if (rpad > 0) { + r.left = x2+width; + r.top = y2-tpad; + r.right = r.left + rpad; + r.bottom = r.top + tpad+height+bpad; + if (stdwin) + FillRect(stddc, &r, hb); + FillRect(pixdc, &r, hb); + } + if (tpad > 0) { + r.left = x2; + r.top = y2-tpad; + r.right = r.left + width; + r.bottom = r.top + tpad; + if (stdwin) + FillRect(stddc, &r, hb); + FillRect(pixdc, &r, hb); + } + if (bpad > 0) { + r.left = x2; + r.top = y2+height; + r.right = r.left + width; + r.bottom = r.top + bpad; + if (stdwin) + FillRect(stddc, &r, hb); + FillRect(pixdc, &r, hb); + } + } + + /* + * free resources + */ + SelectObject(srcpixdc, oldpix); + if (w2->window != w->window) { + ReleaseDC(w->window->iconwin, srcdc); + DeleteDC(srcpixdc); + } + DeleteObject(hb); + FREE_STDLOCALS(w2); + return Succeeded; + } + +int getdefault(w, prog, opt, answer) +wbp w; +char *prog, *opt, *answer; + { + return Failed; + } + +/* + * Draw a bilevel image. + */ +int blimage(w, x, y, width, height, ch, s, len) +wbp w; +int x, y, width, height, ch; +unsigned char *s; +word len; + { + unsigned int m, msk1, c, ix, iy; + long fg, bg; + SysColor palfg, palbg; + STDLOCALS(w); + palfg = PALCLR(wc->fg); + palbg = PALCLR(wc->bg); + /* + * Read the image string and set the pixel values. Note that + * the hex digits in sequence fill the rows *right to left*. + */ + m = width % 4; + if (m == 0) + msk1 = 8; + else + msk1 = 1 << (m - 1); /* mask for first byte of row */ + + fg = wc->fg; + bg = wc->bg; + ix = width; + iy = 0; + m = msk1; + while (len--) { + if (isxdigit(c = *s++)) { /* if hexadecimal character */ + if (!isdigit(c)) /* fix bottom 4 bits if necessary */ + c += 9; + while (m > 0) { /* set (usually) 4 pixel values */ + --ix; + if (c & m) { + SetPixel(pixdc, ix, iy, palfg); + } + else if (ch != TCH1) { /* if zeroes aren't transparent */ + SetPixel(pixdc, ix, iy, palbg); + } + m >>= 1; + } + if (ix == 0) { /* if end of row */ + ix = width; + iy++; + m = msk1; + } + else + m = 8; + } + } + if (ix > 0) /* pad final row if incomplete */ + while (ix < width) + SetPixel(pixdc, ix++, iy, palbg); + + /* + * Put it on the screen. + */ + if (ws->win) + BitBlt(stddc, x, y, width, height, pixdc, x, y, SRCCOPY); + FREE_STDLOCALS(w); + return Succeeded; + } + +/* + * Draw a character-per-pixel image. + */ +int strimage(w, x, y, width, height, e, s, len, on_icon) +wbp w; +int x, y, width, height; +struct palentry *e; +unsigned char *s; +word len; +int on_icon; + { + HDC tempdc; + HBITMAP temppix; + register int c; + register unsigned int ix; + int v, anytransparent=0; + unsigned int iy, tmpw; + SysColor clrlist[256], xc, palbg; + char tmp[24]; + BITMAPINFO *bmi; + BITMAPINFOHEADER *bmih = &(bmi->bmiHeader); + HBITMAP oldpix = 0; + STDLOCALS(w); + + bmi = malloc(sizeof(BITMAPINFO) + 256 * sizeof(SysColor)); + if (bmi == NULL) { + FREE_STDLOCALS(w); + return -1; + } + + bmih = &(bmi->bmiHeader); + palbg = PALCLR(wc->bg); + if (on_icon) { + free(bmi); + FREE_STDLOCALS(w); + return -1; + } + + bmih->biClrImportant = 0; + /* + * Build arrays of colors in SysColor and RGBQUAD format for use by + * either SetPixel or DIB. Decide which to use based on whether + * there are any transparent pixels + */ + for (c = 0; c < 256; c++) { + if (e[c].transpt) anytransparent++; + if (e[c].used && e[c].valid) { + bmih->biClrImportant++; + clrlist[c] = mscolor(w, e[c].clr.red, e[c].clr.green, e[c].clr.blue); + bmi->bmiColors[c].rgbBlue = BLUE(clrlist[c]); + bmi->bmiColors[c].rgbRed = RED(clrlist[c]); + bmi->bmiColors[c].rgbGreen = GREEN(clrlist[c]); + if (alc_rgb(w, clrlist[c]) == Failed) { + free(bmi); + FREE_STDLOCALS(w); + return -1; + } + clrlist[c] = PALCLR(clrlist[c]); + } + else { + bmi->bmiColors[c].rgbBlue = BLUE(wc->bg); + bmi->bmiColors[c].rgbRed = RED(wc->bg); + bmi->bmiColors[c].rgbGreen = GREEN(wc->bg); + } + } + + /* + * if transparent characters are not present, blast out a DIB. + */ + if (anytransparent == 0) { + char *buf = malloc(height * (width+4)), *buf2; + buf2 = buf; + bmih->biSize = sizeof(BITMAPINFOHEADER); + bmih->biWidth = width; + bmih->biHeight = -height; + bmih->biPlanes = 1; + bmih->biBitCount = 8; + bmih->biCompression = BI_RGB; + bmih->biSizeImage = 0; + bmih->biXPelsPerMeter = 0; + bmih->biYPelsPerMeter = 0; + bmih->biClrUsed = 256; + + ix = 0; + while (len--) { + *buf++ = *s++; + if (++ix >= width) { + while(ix % 4) { + buf++; + ix++; + } + ix = 0; + } + } + temppix=CreateDIBitmap(pixdc, bmih, CBM_INIT, buf2, bmi, DIB_RGB_COLORS); + free(buf2); + tempdc = CreateCompatibleDC(stddc); + oldpix = SelectObject(tempdc, temppix); + BitBlt(pixdc, x, y, width, height, tempdc, 0, 0, SRCCOPY); + SelectObject(tempdc, oldpix); + DeleteDC(tempdc); + DeleteObject(temppix); + } + else { + /* + * The image contains some transparent pixels. + * Read the image string and set the pixel values. + * Note that SetPixelV() fails under Win32s; so we don't use it. + */ + ix = x; + iy = y; + tmpw = x + width; + while (len--) { + c = *s++; + v = e[c].valid; + if (v) { /* put char if valid */ + xc = SetPixel(pixdc, ix, iy, clrlist[c]); + } + if (v || e[c].transpt) { /* advance if valid or transparent */ + if (++ix >= tmpw) { + ix = x; /* reset for new row */ + iy++; + } + } + } + if (ix > 0) /* pad final row if incomplete */ + while (ix < width) + SetPixel(pixdc, x+ix++, y+iy, palbg); + } + + free(bmi); + /* + * Copy it from the pixmap onto the screen. + */ + if (on_icon) { + FREE_STDLOCALS(w); + return -1; + } + else { + if (ws->win) + BitBlt(stddc, x, y, width, height, pixdc, x, y, SRCCOPY); + } + FREE_STDLOCALS(w); + return 0; + } + +/* + * imqsearch(key,base,nel) - binary search hardwired for images + * + * A binary search routine with arguments similar to qsort(3). + * Returns a pointer to the item matching "key", or NULL if none. + * This is called a LOT, so it is hardwired for speed. + * Based on Bentley, CACM 28,7 (July, 1985), p. 676. + */ + +SysColor * imqsearch (SysColor key, SysColor *base, int nel) +{ + int l, u, m; + SysColor * a; + + l = 0; + u = nel - 1; + while (l <= u) { + m = (l + u) / 2; + a = base + m; + if (*a < key) + l = m + 1; + else if (*a > key) + u = m - 1; + else + return a; + } + while (a>base && key < *a) a--; + while (a<base+nel && key > *a) a++; + return a; +} + +/* + * capture -- get an image region. + * + * Stores the specified subimage in data as 15-bit color. + */ +int capture(w, xx, yy, width, height, data) +wbp w; +int xx, yy, width, height; +short *data; + { + SysColor px; + int r, g, b, x, y; + int wd = xx + width; + int ht = yy + height; + STDLOCALS(w); + + for (y = yy; y < ht; y++) { + for (x = xx; x < wd; x++) { + px = GetPixel(pixdc, x, y); + r = RED(px) >> 3; + g = GREEN(px) >> 3; + b = BLUE(px) >> 3; + *data++ = (r << 10) | (g << 5) | b; + } + } + FREE_STDLOCALS(w); + return 1; + } + +int readimage(w, filename, x, y, status) +wbp w; +char *filename; +int x, y, *status; + { + HBITMAP p, oldpix; + unsigned int width, height; + HDC srcdc, srcpixdc; + + if (!x && !y) + p = loadimage(w, filename, &width, &height, 1, status); + else + p = loadimage(w, filename, &width, &height, 0, status); + + if (p == (HBITMAP) NULL) { + return Failed; + } + + { + STDLOCALS(w); + + srcdc = GetDC(ws->iconwin); + srcpixdc = CreateCompatibleDC(srcdc); + oldpix = SelectObject(srcpixdc, p); + BitBlt(pixdc, x, y, width, height, srcpixdc, 0, 0, SRCCOPY); + if (stdwin) + BitBlt(stddc, x, y, width, height, srcpixdc, 0, 0, SRCCOPY); + SelectObject(srcpixdc, oldpix); + ReleaseDC(ws->iconwin, srcdc); + DeleteDC(srcpixdc); + + /* + * Make sure previous ops on p are complete, then free it. + */ + DeleteObject(p); + FREE_STDLOCALS(w); + return Succeeded; + } + } + + + +/* + * Initialize client for producing pixels from a window, or in this case, + * only create a device context once, not once per getpixel. + */ +int getpixel_init(w, imem) +wbp w; +struct imgmem *imem; + { + COLORREF *p; + wsp ws = w->window; + int i, j, x2, y2; + HDC stddc = GetDC(ws->iconwin), pixdc = CreateCompatibleDC(stddc); + HBITMAP oldpix; + + if (palette) SelectPalette(pixdc, palette, FALSE); + oldpix = SelectObject(pixdc, ws->pix); + + /* this looks like a bug for Win16 for images > 100x100 or so... */ + imem->crp = malloc( imem->width * imem->height * sizeof(COLORREF)); + if (imem->crp == NULL) return Failed; + p = imem->crp; + x2 = imem->x + imem->width; + y2 = imem->y + imem->height; + for(i = imem->y; i < y2; i++) + for(j = imem->x; j < x2; j++) { + if ((*p++ = GetPixel(pixdc, j, i)) == (COLORREF)-1L) { + free(imem->crp); + SelectObject(pixdc, oldpix); + FREE_STDLOCALS(w); + return Failed; + } + } + SelectObject(pixdc, oldpix); + FREE_STDLOCALS(w); + return Succeeded; + } + +int getpixel_term(w, imem) +wbp w; +struct imgmem *imem; +{ + free(imem->crp); + return Succeeded; +} + +/* + * Return pixel (x,y) from a window + */ +int getpixel(wbp w, int x, int y, long *rv, char *s, struct imgmem *imem) + { + COLORREF cr = imem->crp[(y-imem->y) * imem->width + (x-imem->x)]; + *rv = 1; + sprintf(s, "%ld,%ld,%ld", + (long)RED(cr)*257L, (long)GREEN(cr)*257L, (long)BLUE(cr)*257L); + return Succeeded; + } + +int query_pointer(w, pp) +wbp w; +XPoint *pp; + { + wsp ws = w->window; + RECT r; + if (ws->win) { + GetCursorPos(pp); + GetWindowRect(ws->win, &r); + pp->x -= r.left; + pp->y -= r.top; + return Succeeded; + } + return Failed; + } + +int query_rootpointer(pp) +XPoint *pp; + { + GetCursorPos(pp); + return Succeeded; + } + +int seticonimage(w, dp) +wbp w; +dptr dp; + { + wsp ws = w->window; + return Succeeded; + } + +/* + * dumpimage -- write an image to a disk file. Return 0 on failure. + */ +int dumpimage(wbp w, char *filename, unsigned int x, unsigned int y, + unsigned int width, unsigned int height) + { + int result = 0; + HDIB dib; + HDC destdc; + HBITMAP dumppix, oldpix; + STDLOCALS(w); + + if (strcmp(".bmp", filename + strlen(filename) - 4) && + strcmp(".BMP", filename + strlen(filename) - 4)) { + FREE_STDLOCALS(w); + return NoCvt; + } + + /* + * extract the desired rectangle from the source bitmap + */ + if (x || y || width != ws->pixwidth || height != ws->pixheight) { + dumppix = CreateCompatibleBitmap(stddc, width, height); + destdc = CreateCompatibleDC(stddc); + oldpix = SelectObject(destdc, dumppix); + BitBlt(destdc, 0, 0, width, height, pixdc, x, y, SRCCOPY); + } + else dumppix = ws->pix; + dib = BitmapToDIB(dumppix, palette); + if (dumppix != ws->pix) { + SelectObject(destdc, oldpix); + DeleteDC(destdc); + DeleteObject(dumppix); + } + + if (dib == NULL) { + result = Failed; + } + else { + if (result = SaveDIB(dib, filename)) { /* != 0 implies error */ + result = Failed; + } + else { + result = Succeeded; + } + DestroyDIB(dib); + } + + FREE_STDLOCALS(w); + return result; + } + + +/* + * loadimage + */ +HBITMAP loadimage(wbp w, char *filename, unsigned int *width, + unsigned int *height, int atorigin, int *status) + { + HDC hdc; + HDIB dib; + HBITMAP bmap; + HPALETTE p2; + PALETTEENTRY pe; + LPBITMAPINFO lpbmi; + int j; + int ii,jj, kk; + int xx[256]; + unsigned char * pd; + char *j2; + + dib = LoadDIB(filename); + if (dib != NULL) { + LPSTR pdib; + p2 = CreateDIBPalette(dib); + j2 = GlobalLock(dib); + j = DIBNumColors(j2); + jj = DIBWidth(j2); + kk = DIBHeight(j2); + GlobalUnlock(dib); + + if (!palette) { + LOGPALETTE logpal[4]; /* (1, + space for an extra palette entry) */ + hdc = GetDC(w->window->iconwin); + if ((GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) && (numColors ==0)){ + /* This window is on a device that supports palettes */ + numColors = 2; + logpal[0].palNumEntries = 2; + logpal[0].palVersion = 0x300; + logpal[0].palPalEntry[0].peFlags = 0; + logpal[0].palPalEntry[0].peRed = 0; + logpal[0].palPalEntry[0].peGreen = 0; + logpal[0].palPalEntry[0].peBlue = 0; + logpal[0].palPalEntry[1].peFlags = 0; + logpal[0].palPalEntry[1].peRed = 255; + logpal[0].palPalEntry[1].peGreen = 255; + logpal[0].palPalEntry[1].peBlue = 255; + palette = CreatePalette(logpal); + if (!palette) { + return NULL; + } + if ((scp = malloc(2 * sizeof (struct wcolor))) == NULL) + return NULL; + scp[0].c = RGB(0,0,0); + scp[0].type = SHARED; + strcpy(scp[0].name, "black"); + scp[1].c = RGB(255,255,255); + scp[1].type = SHARED; + strcpy(scp[1].name, "white"); + } + else { + /* this window is not on a device that supports palettes */ + } + ReleaseDC(w->window->iconwin, hdc); + } + if (palette) { + if (ResizePalette(palette, numColors + j) == 0) { + return NULL; + } + for (ii = 0; ii < j; ii++) { + if (GetPaletteEntries(p2, ii, 1, &pe) == 0) { + return NULL; + } + SetPaletteEntries(palette, numColors++, 1, &pe); + } + } + bmap = DIBToBitmap(dib, palette); + pdib = GlobalLock(dib); + *width = DIBWidth(pdib); + *height = DIBHeight(pdib); + GlobalUnlock(dib); + DestroyDIB(dib); + DeleteObject(p2); + *status = 0; + return bmap; + } + return NULL; + } + + +char *get_mutable_name(wbp w, int mute_index) + { + char *tmp; + PALETTEENTRY pe; + + if (-mute_index > numColors || scp[-mute_index].type != MUTABLE) { + return NULL; + } + + if (GetPaletteEntries(palette, -mute_index, 1, &pe) == 0) { + return NULL; + } + tmp = scp[-mute_index].name; + sprintf(tmp, "%d", mute_index); + sprintf(tmp + strlen(tmp) + 1, "%d,%d,%d", + (pe.peRed << 8) | 0xff, (pe.peGreen << 8) | 0xff, (pe.peBlue << 8) | 0xff); + return tmp + strlen(tmp) + 1; + } + +int set_mutable(wbp w, int i, char *s) + { + long r, g, b; + UINT rv; + PALETTEENTRY pe; + if (palette == 0) return Failed; + + { + STDLOCALS(w); + if (parsecolor(w, s, &r, &g, &b) != Succeeded) { + FREE_STDLOCALS(w); + return Failed; /* invalid color specification */ + } + pe.peRed = r >> 8; + pe.peGreen = g >> 8; + pe.peBlue = b >> 8; + pe.peFlags = PC_RESERVED; + raiseWindow(w); /* mutable won't mutate if window isn't active */ +#if 1 + AnimatePalette(palette, -i, 1, &pe); + rv = SetPaletteEntries(palette, -i, 1, &pe); +#endif + UnrealizeObject(palette); + RealizePalette(stddc); + AnimatePalette(palette, -i, 1, &pe); + FREE_STDLOCALS(w); +} + return Succeeded; + } + +void free_mutable(wbp w, int mute_index) + { + } + +/* + * Allocate a mutable color + */ +int mutable_color(wbp w, dptr argv, int argc, int *retval) + { + long r, g, b; + tended char *str; + LOGPALETTE lp; + { + STDLOCALS(w); + + if (!stddc || ((GetDeviceCaps(stddc, RASTERCAPS) & RC_PALETTE) == 0)) { + FREE_STDLOCALS(w); + return Failed; + } + + numColors++; + scp = realloc(scp, numColors * sizeof(struct wcolor)); + if (scp == NULL) { + FREE_STDLOCALS(w); + return Failed; + } + scp[numColors-1].c = -(numColors-1); + sprintf(scp[numColors-1].name, "%d:", -(numColors-1)); + scp[numColors-1].type = MUTABLE; + if (ResizePalette(palette, numColors) == 0) { + FREE_STDLOCALS(w); + return Failed; + } + + if (argc > 0) { /* set the color */ + if (argc != 1) { + FREE_STDLOCALS(w); + return Error; + } + /* + * old-style check for C integer + */ + else if (argv[0].dword == D_Integer) {/* check for color cell */ + if (IntVal(argv[0]) >= 0) { + FREE_STDLOCALS(w); + return Failed; /* must be negative */ + } + if (GetPaletteEntries(palette, -IntVal(argv[0]), + 1, lp.palPalEntry) == 0) { + FREE_STDLOCALS(w); + return Error; + } + /* convert to linear color? */ + } + else { + if (!cnv:C_string(argv[0],str)) { + FREE_STDLOCALS(w); + ReturnErrVal(103,argv[0], Error); + } + if (parsecolor(w, str, &r, &g, &b) != Succeeded) { + /* reduce logical palette size and count */ + FREE_STDLOCALS(w); + numColors--; + ResizePalette(palette, numColors); + return Failed; /* invalid color specification */ + } + lp.palPalEntry[0].peRed = r >> 8; + lp.palPalEntry[0].peGreen = g >> 8; + lp.palPalEntry[0].peBlue = b >> 8; + } + lp.palNumEntries = 1; + lp.palVersion = 0x300; + lp.palPalEntry[0].peFlags = PC_RESERVED; + SetPaletteEntries(palette, numColors - 1, 1, lp.palPalEntry); + UnrealizeObject(palette); + RealizePalette(stddc); + } + + *retval = -(numColors - 1); + FREE_STDLOCALS(w); + return Succeeded; + } + } + +void freecolor(wbp w, char *s) + { + } + +/* + * drawarcs() - assumes x and y are already fixed up for the bitmap + */ +void drawarcs(wbp wb, XArc *arcs, int narcs) + { + register XArc *arc = arcs; + int i, halfwidth, halfheight, x1, y1, x2, y2, right, bottom; + double a1_a2; + HPEN hp, oldpen, oldpen2; + STDLOCALS(wb); + hp = CreatePenIndirect(&(wc->pen)); + if (stdwin) oldpen = SelectObject(stddc, hp); + oldpen2 = SelectObject(pixdc, hp); + for (i = 0; i < narcs; i++, arc++) { + halfwidth = arc->width >> 1; + halfheight = arc->height >> 1; + arc->angle1 = -arc->angle1 - arc->angle2; + a1_a2 = arc->angle1 + arc->angle2; + x1 = arc->x + halfwidth + (int)(halfwidth * cos(arc->angle1)); + y1 = arc->y + halfheight - (int)(halfheight * sin(arc->angle1)); + x2 = arc->x + halfwidth + (int)(halfwidth * cos(a1_a2)); + y2 = arc->y + halfheight - (int)(halfheight * sin(a1_a2)); + right = arc->x + arc->width + 1; + bottom = arc->y + arc->height + 1; + if (ws->win) + Arc(stddc, arc->x, arc->y, right, bottom, x1, y1, x2, y2); + Arc(pixdc, arc->x, arc->y, right, bottom, x1, y1, x2, y2); + } + if (stdwin) SelectObject(stddc, oldpen); + SelectObject(pixdc, oldpen2); + DeleteObject(hp); + FREE_STDLOCALS(wb); + return; + } + + +/* + * drawlines - Support routine for DrawLine + */ +void drawlines(wbinding *wb, XPoint *points, int npoints) + { + int i, diff, bheight; + HPEN hp, oldpen, oldpen2; + XPoint tmp[2]; + STDLOCALS(wb); + hp = CreatePenIndirect(&(wc->pen)); + if (stdwin) oldpen = SelectObject(stddc, hp); + oldpen2 = SelectObject(pixdc, hp); + tmp[0] = points[npoints-1]; + tmp[1] = points[npoints-2]; + if (ws->win) { + SetBkMode(stddc, wc->bkmode); + Polyline(stddc, points, npoints); + Polyline(stddc, tmp, 2); + } + SetBkMode(pixdc, wc->bkmode); + Polyline(pixdc, points, npoints); + Polyline(pixdc, tmp, 2); + if (stdwin) SelectObject(stddc, oldpen); + SelectObject(pixdc, oldpen2); + DeleteObject(hp); + FREE_STDLOCALS(wb); + return; + } + + +/* + * drawpoints() - + * Parameters - the window binding for output, an array of points (assumed + * to be fixed up for bitmap) and the number of points + */ +void drawpoints(wbinding *wb, XPoint *points, int npoints) + { + register XPoint *p, *endp; + SysColor palfg; + STDLOCALS(wb); + endp = points + npoints; + palfg = PALCLR(wc->fg); + if (stdwin) { + for(p = points; p < endp; p++) { + SetPixel(stddc, p->x, p->y, palfg); + SetPixel(pixdc, p->x, p->y, palfg); + } + } + else { + for(p = points; p < endp; p++) { + SetPixel(pixdc, p->x, p->y, palfg); + } + } + FREE_STDLOCALS(wb); + return; + } + + +/* + * drawsegments() - + */ +void drawsegments(wbinding *wb, XSegment *segs, int nsegs) + { + int i, bheight; + XPoint ps[2]; + HPEN hp, oldpen, oldpen2; + STDLOCALS(wb); + hp = CreatePenIndirect(&(wc->pen)); + if (stdwin) oldpen = SelectObject(stddc, hp); + oldpen2 = SelectObject(pixdc, hp); + if (stdwin) { + SetBkMode(stddc, wc->bkmode); + for (i = 0; i < nsegs; i++) { + Polyline(stddc, (POINT *)(segs+i), 2); + } + } + SetBkMode(pixdc, wc->bkmode); + for (i = 0; i < nsegs; i++) { + Polyline(pixdc, (POINT *)(segs+i), 2); + } + if (stdwin) SelectObject(stddc, oldpen); + SelectObject(pixdc, oldpen2); + DeleteObject(hp); + FREE_STDLOCALS(wb); + return; + } + + +int allowresize(w, on) +wbp w; +int on; + { + if (on) + SETRESIZABLE(w); + else + CLRRESIZABLE(w); + return Succeeded; + } +int getselection(wbp w, char *buf) +{ + return Failed; + } +int setselection(wbp w, char *val) +{ + return Failed; + } + +/* + * drawstrng() + */ +void drawstrng(wbinding *wb, int x, int y, char *s, int slen) + { + STDLOCALS(wb); + + STDFONT; + if (stdwin) { + SetBkMode(stddc, TRANSPARENT); + if (wc->fg != RGB(0, 0, 0)) SetTextColor(stddc, PALCLR(wc->fg)); + if (wc->bg != RGB(255, 255, 255)) SetBkColor(stddc, PALCLR(wc->bg)); + TextOut(stddc, x, y - ASCENT(wb), s, slen); + } + SetBkMode(pixdc, TRANSPARENT); + if (wc->fg != RGB(0, 0, 0)) SetTextColor(pixdc, PALCLR(wc->fg)); + if (wc->bg != RGB(255, 255, 255)) SetBkColor(pixdc, PALCLR(wc->bg)); + TextOut(pixdc, x, y - ASCENT(wb), s, slen); + + FREE_STDLOCALS(wb); + return; + } + + +/* + * fillarcs + */ +void fillarcs(wbp wb, XArc *arcs, int narcs) + { + register XArc *arc = arcs; + int i, diff, bheight; + HBRUSH hb, oldbrush, oldbrush2; + POINT pts[3]; + HPEN hp, oldpen, oldpen2; + STDLOCALS(wb); + hp = CreatePenIndirect(&(wc->pen)); + if (stdwin) oldpen = SelectObject(stddc, hp); + oldpen2 = SelectObject(pixdc, hp); + hb = CreateBrushIndirect(&(wc->brush)); + if (stdwin) oldbrush = SelectObject(stddc, hb); + oldbrush2 = SelectObject(pixdc, hb); + SetTextColor(pixdc, PALCLR(wc->fg)); + if (stdwin) SetTextColor(stddc, PALCLR(wc->fg)); + SetBkColor(pixdc, PALCLR(wc->bg)); + if (stdwin) SetBkColor(stddc, PALCLR(wc->bg)); + if (stdwin) SetBkMode(stddc, wc->bkmode); + SetBkMode(pixdc, wc->bkmode); + for (i = 0; i < narcs; i++, arc++) { + if (arc->angle2 >= 2 * Pi) { + /* + * from SDK reference: Ellipse() draws up to but not including + * the right and bottom coordinates. Add +1 to compensate. + */ + if (stdwin) + Ellipse(stddc, arc->x, arc->y, + arc->x + arc->width + 1, arc->y + arc->height + 1); + Ellipse(pixdc, arc->x, arc->y, + arc->x + arc->width + 1, arc->y + arc->height + 1); + } + else { + arc->angle1 = -arc->angle1 - arc->angle2; + pts[0].x = arc->x + (arc->width>>1); + pts[0].y = arc->y + (arc->height>>1); + pts[1].x = arc->x + (arc->width>>1) + + (int)(((arc->width + 1)>>1) * cos(arc->angle1)); + pts[1].y = arc->y + (arc->height>>1) - + (int)(((arc->height )>>1) * sin(arc->angle1)); + pts[2].x = arc->x + (arc->width>> 1) + + (int)(((arc->width + 1)>>1) * cos(arc->angle1+arc->angle2)); + pts[2].y = arc->y + (arc->height>>1) - + (int)(((arc->height )>>1) * sin(arc->angle1+arc->angle2)); + if (stdwin) { + Pie(stddc, arc->x, arc->y, + arc->x + arc->width + 1, arc->y + arc->height + 1, + pts[1].x, pts[1].y, pts[2].x, pts[2].y); + } + Pie(pixdc, arc->x, arc->y, + arc->x + arc->width + 1, arc->y + arc->height + 1, + pts[1].x, pts[1].y, pts[2].x, pts[2].y); + } + } + if (stdwin) SelectObject(stddc, oldpen); + SelectObject(pixdc, oldpen2); + DeleteObject(hp); + if (stdwin) SelectObject(stddc, oldbrush); + SelectObject(pixdc, oldbrush2); + DeleteObject(hb); + FREE_STDLOCALS(wb); + return; + } + +/* + * fillrectangles + */ +void fillrectangles(wbp wb, XRectangle *recs, int nrecs) + { + int i, diff, bheight; + HBRUSH hb, oldbrush, oldbrush2; + HPEN hp, oldpen, oldpen2; + STDLOCALS(wb); + hp = CreatePenIndirect(&(wc->pen)); + if (stdwin) oldpen = SelectObject(stddc, hp); + oldpen2 = SelectObject(pixdc, hp); + hb = CreateBrushIndirect(&(wc->brush)); + if (stdwin) oldbrush = SelectObject(stddc, hb); + oldbrush2 = SelectObject(pixdc, hb); + SetTextColor(pixdc, PALCLR(wc->fg)); + if (stdwin) SetTextColor(stddc, PALCLR(wc->fg)); + SetBkColor(pixdc, PALCLR(wc->bg)); + if (stdwin) SetBkColor(stddc, PALCLR(wc->bg)); + if (stdwin) SetBkMode(stddc, wc->bkmode); + SetBkMode(pixdc, wc->bkmode); + for (i = 0; i < nrecs; i++) { + recs[i].right += recs[i].left; + recs[i].bottom += recs[i].top; + if (stdwin) FillRect(stddc, (recs+i), hb); + FillRect(pixdc, (recs+i), hb); + } + if (stdwin) SelectObject(stddc, oldpen); + SelectObject(pixdc, oldpen2); + DeleteObject(hp); + if (stdwin) SelectObject(stddc, oldbrush); + SelectObject(pixdc, oldbrush2); + DeleteObject(hb); + FREE_STDLOCALS(wb); + return; + } + + +/* + * drawrectangles - draw nrecs # of rectangles in array recs to binding w + */ +void drawrectangles(wbp w, XRectangle *recs, int nrecs) + { + register XRectangle *r; + LOGBRUSH lb; + HBRUSH hb, oldbrush, oldbrush2; + HPEN hp, oldpen, oldpen2; + STDLOCALS(w); + hp = CreatePenIndirect(&(wc->pen)); + if (stdwin) oldpen = SelectObject(stddc, hp); + oldpen2 = SelectObject(pixdc, hp); + lb.lbStyle = BS_NULL; + hb = CreateBrushIndirect(&lb); + if (stdwin) oldbrush = SelectObject(stddc, hb); + oldbrush2 = SelectObject(pixdc, hb); + for (r = recs; r < recs + nrecs; r++) { + /* + * from SDK reference: Rectangle() draws up to but not including + * the right and bottom coordinates. Add +1 to compensate. + */ + r->right += r->left + 1; + r->bottom += r->top + 1; + if (stdwin) Rectangle(stddc, r->left, r->top, r->right, r->bottom); + Rectangle(pixdc, r->left, r->top, r->right, r->bottom); + } + if (stdwin) SelectObject(stddc, oldpen); + SelectObject(pixdc, oldpen2); + DeleteObject(hp); + if (stdwin) SelectObject(stddc, oldbrush); + SelectObject(pixdc, oldbrush2); + DeleteObject(hb); + FREE_STDLOCALS(w); + return; + } + +/* + * fillpolygon + */ +void fillpolygon(wbp w, XPoint *pts, int npts) + { + HBRUSH hb, oldbrush; + HPEN hp, oldpen, oldpen2; + STDLOCALS(w); + if (stdwin) SetBkMode(stddc, wc->bkmode); + SetBkMode(pixdc, wc->bkmode); + hp = CreatePenIndirect(&(wc->pen)); + if (stdwin) oldpen = SelectObject(stddc, hp); + oldpen2 = SelectObject(pixdc, hp); + hb = CreateBrushIndirect(&(wc->brush)); + if (stdwin) { + oldbrush = SelectObject(stddc, hb); + Polygon(stddc, pts, npts); + SelectObject(stddc, oldbrush); + } + oldbrush = SelectObject(pixdc, hb); + Polygon(pixdc, pts, npts); + SelectObject(pixdc, oldbrush); + DeleteObject(hb); + if (stdwin) SelectObject(stddc, oldpen); + SelectObject(pixdc, oldpen2); + DeleteObject(hp); + FREE_STDLOCALS(w); + } + +LONG NumWindows = 0; + + +/* + * allocate a context. Can't be called until w has a display and window. + */ +wcp alc_context(w) +wbp w; + { + int i; + wcp wc; + + GRFX_ALLOC(wc, _wcontext); + + wc->bkmode = OPAQUE; /* at present, only used in line drawing */ + wc->fg = RGB(0,0,0); + wc->bg = RGB(255,255,255); + wc->fgname = salloc("black"); + wc->bgname = salloc("white"); + wc->pen.lopnStyle = PS_SOLID; + wc->pen.lopnWidth.x = wc->pen.lopnWidth.y = 1; + wc->pen.lopnColor = PALCLR(wc->fg); + wc->bgpen.lopnStyle = PS_SOLID; + wc->bgpen.lopnWidth.x = wc->bgpen.lopnWidth.y = 1; + wc->bgpen.lopnColor = PALCLR(wc->bg); + wc->fillstyle = BS_SOLID; + wc->brush.lbStyle = BS_SOLID; + wc->brush.lbColor = PALCLR(wc->fg); + wc->bgbrush.lbStyle = BS_SOLID; + wc->bgbrush.lbColor = PALCLR(wc->bg); + wc->gamma = GammaCorrection; + wc->drawop = R2_COPYPEN; + wc->font = (wfp)alloc(sizeof (struct _wfont)); + wc->font->name = salloc("fixed"); + wc->font->font = CreateFont(16,0,0,0,FW_NORMAL,0,0,0, + ((MAXBYTESPERCHAR==1)?ANSI_CHARSET:DEFAULT_CHARSET), + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, + getenv("ICONFONT")); + + wc->font->charwidth = 8; /* looks like a bug */ + wc->leading = 16; + + GRFX_LINK(wc, wcntxts); + return wc; + } + +/* + * allocate a context, cloning attributes from an existing context + */ +wcp clone_context(w) +wbp w; + { + wcp wc, wc2 = w->context; + wsp ws = w->window; + wbinding tmp; + int i; + + GRFX_ALLOC(wc, _wcontext); + + tmp.window = ws; + tmp.context = wc; + /* + * copy over some stuff + */ + wc->clipx = wc2->clipx; + wc->clipy = wc2->clipy; + wc->clipw = wc2->clipw; + wc->cliph = wc2->cliph; + if (wc2->cliprgn) + wc->cliprgn = CreateRectRgn(wc->clipx,wc->clipy, + wc->clipx+wc->clipw, + wc->clipy+wc->cliph); + wc->dx = wc2->dx; + wc->dy = wc2->dy; + wc->bits = wc2->bits; + /* + * clone needs to make a copy of the pattern + * if (wc2->pattern) { + * wc->pattern = copy+somehow(wc2->pattern); + * if (wc2->patternname) + * wc->patternname = salloc(wc2->patternname); + * } + */ + + wc->bkmode = wc2->bkmode; + wc->fg = wc2->fg; + wc->bg = wc2->bg; + wc->fgname = salloc(wc2->fgname); + wc->bgname = salloc(wc2->bgname); + wc->pen = wc2->pen; + if (ISXORREVERSEW(wc)) { + wc->brush.lbColor = PALCLR((wc->fg ^ wc->bg) & 0x00FFFFFF); + } + else { + wc->brush.lbColor = PALCLR(wc->fg); + } + wc->bgpen = wc2->bgpen; + wc->fillstyle = wc2->fillstyle; + wc->brush.lbStyle = wc->fillstyle; + wc->bgbrush.lbStyle = wc->fillstyle; + wc->bgbrush.lbColor = PALCLR(wc->bg); + wc->gamma = wc2->gamma; + wc->drawop = wc2->drawop; + wc->font = (wfp)alloc(sizeof (struct _wfont)); + wc->font->name = salloc("fixed"); + wc->font->font = CreateFont(13,0,0,0,FW_NORMAL,0,0,0, + ((MAXBYTESPERCHAR==1)?ANSI_CHARSET:DEFAULT_CHARSET), + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, + getenv("ICONFONT")); + wc->leading = wc2->leading; + setfont(&tmp, &(wc2->font->name)); + + GRFX_LINK(wc, wcntxts); + return wc; + } + +/* + * allocate a window state structure + */ +wsp alc_winstate() + { + int i; + wsp ws; + + GRFX_ALLOC(ws, _wstate); + ws->bits = 1024; /* echo ON; others OFF */ + ws->filep = nulldesc; + ws->listp = nulldesc; + ws->cursorname = salloc("arrow"); + ws->curcursor = LoadCursor(NULL, IDC_ARROW); + GRFX_LINK(ws, wstates); + return ws; + } + +/* + * free a window state + */ +int free_window(ws) +wsp ws; + { + int i; + ws->refcount--; + if(ws->refcount == 0) { + if (ws->win) /* && IsWindowVisible(ws->win))*/ + DestroyWindow(ws->win); +/* ws->win = 0;*/ + if (ws->iconwin && ws->iconwin != ws->win) { + if (IsWindowVisible(ws->iconwin)) + DestroyWindow(ws->iconwin); + else DestroyWindow(ws->iconwin); + } +/* ws->iconwin = 0;*/ +/* while (ws->win) + if (pollevent() == -1) return -1; +*/ + if (ws->windowlabel) free(ws->windowlabel); + if (ws->iconlabel) free(ws->iconlabel); + if (ws->pix) + DeleteObject(ws->pix); + ws->pix = 0; + if (ws->iconpix) + DeleteObject(ws->iconpix); + ws->iconpix = 0; + if (ws->initialPix) + DeleteObject(ws->initialPix); + ws->initialPix = 0; + /* need to enumerate and specifically free each string */ + if (ws->menuMap) { + for(i=0;i<ws->nmMapElems;i++) free(ws->menuMap[i]); + free(ws->menuMap); + ws->menuMap = 0; + } + free(ws->cursorname); + if (ws->child) { + for(i=0;i<ws->nChildren;i++) { + free(ws->child[i].id); + if (ws->child[i].font) DeleteObject(ws->child[i].font); + } + free(ws->child); + } + ws->child = 0; + GRFX_UNLINK(ws, wstates); + } + return 0; + } + +/* + * free a window context + */ +void free_context(wc) +wcp wc; + { + wc->refcount--; + if(wc->refcount == 0) { + if (wc->cliprgn) + DeleteObject(wc->cliprgn); + wc->cliprgn = 0; + if (wc->pattern) + DeleteObject(wc->pattern); + wc->pattern = 0; + if (wc->patternname) + free(wc->patternname); + wc->patternname = 0; + if (wc->fgname) free(wc->fgname); + wc->fgname = 0; + if (wc->bgname) free(wc->bgname); + wc->bgname = 0; + if (wc->font) { + if (wc->font->font) + DeleteObject(wc->font->font); + wc->font->font = 0; + if (wc->font->name) + free(wc->font->name); + wc->font->name = 0; + free(wc->font); + } + wc->font = 0; + GRFX_UNLINK(wc, wcntxts); + } + } + +int walert(wbp w, int volume) + { + MessageBeep(0); + } + +int patbits[] = { + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFE,0xFF,0xEF,0xFF,0xFE,0xFF,0xEF,0xFF, + 0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD, + 0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA, + 0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44, + 0x01,0x00,0x10,0x00,0x01,0x00,0x10,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01, + 0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00, + 0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x10, + 0x82,0x44,0x28,0x10,0x28,0x44,0x82,0x01, + + 0x0F,0x0F,0x0F,0x0F,0xF0,0xF0,0xF0,0xF0, + 0x1B,0x18,0x81,0xB1,0x36,0x06,0x60,0x63, + 0x02,0x02,0x05,0xF8,0x20,0x20,0x50,0x8F, + 0x03,0x84,0x48,0x30,0x03,0x84,0x48,0x30, +}; + +/* + * SetPattern + */ +int SetPattern(w, name, len) +wbp w; +char *name; +int len; + { + int width, nbits; + int i, j; + int symbol; + C_integer v, bits[MAXXOBJS]; + HBITMAP p; + char data[MAXXOBJS]; + char *buf = data; + wcp wc = w->context; + + if (wc->patternname != NULL) + free(wc->patternname); + wc->patternname = malloc(len+1); + strncpy(wc->patternname, name, len); + wc->patternname[len] = '\0'; + + /* + * If the pattern starts with a number it is a width , bits encoding + */ + if ((len > 0) && isdigit(name[0])) { + nbits = MAXXOBJS; + switch (parsepattern(name, len, &width, &nbits, bits)) { + case Failed: + return Failed; + case Error: + ReturnErrNum(145, Error); + } + if (w->window->iconwin == NULL) return Succeeded; + return SetPatternBits(w, width, bits, nbits); + } + + /* + * Otherwise, it is a named pattern. Find the symbol id. + */ + if ((symbol = si_s2i(siPatternSyms, wc->patternname)) >= 0) { + if (w->window->iconwin == NULL) return Succeeded; + for(i = 0; i < 8; i++) { + v = reversebits(~(patbits[symbol * 8 + i])); + *buf++ = v; + } + p = CreateBitmapFromData(data); + if (wc->pattern) + DeleteObject(wc->pattern); + wc->pattern = p; + if (wc->fillstyle == BS_PATTERN) { + wc->brush.lbStyle = BS_PATTERN; + wc->brush.lbColor = PALCLR(wc->fg); + wc->brush.lbHatch = (LONG)p; + } + return Succeeded; + } + ReturnErrNum(145, Error); + } + +/* + * Create an 8x8 bitmap from some data + */ +HBITMAP CreateBitmapFromData(char *data) +{ + WORD *wBits = alloc(8 * sizeof(WORD)); + HBITMAP rv; + int i; + static BITMAP bitmap = { 0, 8, 8, 2, 1, 1}; + for (i = 0; i < 8; i++) + wBits[i] = data[i]; + bitmap.bmBits = (LPSTR) wBits; + rv = CreateBitmapIndirect(&bitmap); + free(wBits); + return rv; +} + + +int SetPatternBits(w, width, bits, nbits) +wbp w; +int width; +C_integer *bits; +int nbits; + { + C_integer v; + int i, j, k; + HBITMAP p; + char data[MAXXOBJS]; + char *buf = data; + wcp wc = w->context; + + if (width != nbits) + return Failed; + + if (width == 8) { + for(i = 0; i < nbits; i++) { + v = bits[i]; + *buf++ = reversebits(~v); + } + } + else if (width == 4) { + for(k=0; k < 2; k++) /* do twice to get 8 rows */ + for(i = 0; i < nbits; i++) { + v = widenbits(bits[i]); + *buf++ = reversebits(~v); + } + } + else return Failed; + + p = CreateBitmapFromData(data); + if (wc->pattern) + DeleteObject(wc->pattern); + wc->pattern = p; + if (wc->fillstyle == BS_PATTERN) { + wc->brush.lbStyle = BS_PATTERN; + wc->brush.lbColor = PALCLR(wc->fg); + wc->brush.lbHatch = (LONG)p; + } + return Succeeded; + } + +int widenbits(int c) +{ + int rv = c; + if (c & 1) rv |= 16; + if (c & 2) rv |= 32; + if (c & 4) rv |= 64; + if (c & 8) rv |= 128; + return rv; +} + +int reversebits(int c) +{ + int rv = 0; + if (c & 1) rv |= 128; + if (c & 2) rv |= 64; + if (c & 4) rv |= 32; + if (c & 8) rv |= 16; + if (c & 16) rv |= 8; + if (c & 32) rv |= 4; + if (c & 64) rv |= 2; + if (c & 128) rv |= 1; + return rv; +} + +int pixmap_init(w) +wbp w; + { + wsp ws = w->window; + resizePixmap(w, ws->width, ws->height); + return Succeeded; + } + + +int do_config(w, status) +wbp w; +int status; + { + wsp ws = w->window; + int wid = ws->width, ht = ws->height; + int posx = ws->posx, posy = ws->posy; + if (! resizePixmap(w, wid, ht)) + return Failed; + if (ws->win) { + pollevent(); + if (status == 3) { + SetWindowPos(ws->win, ws->win, + posx, + posy, + wid, ht, SWP_NOZORDER); + } + else if (status == 2) { + SetWindowPos(ws->win, ws->win, 0, 0, + wid, ht, SWP_NOMOVE|SWP_NOZORDER); + } + else if (status == 1) + SetWindowPos(ws->win, ws->win, + posx, + posy, + 0, 0, SWP_NOSIZE|SWP_NOZORDER); + } + else if (ws->iconwin) { + if (status == 3) { + SetWindowPos(ws->iconwin, ws->iconwin, + posx, + posy, + wid, ht, SWP_NOZORDER); + } + else if (status == 2) { + SetWindowPos(ws->iconwin, ws->iconwin, 0, 0, + wid, ht, SWP_NOMOVE|SWP_NOZORDER); + } + else if (status == 1) + SetWindowPos(ws->iconwin, ws->iconwin, + posx, + posy, + 0, 0, SWP_NOSIZE|SWP_NOZORDER); + } + return Succeeded; + } + +DWORD playMIDIfile(HWND hWndNotify, LPSTR s) +{ + UINT wDeviceID; + DWORD dwReturn; + MCI_OPEN_PARMS mciOpenParms; + MCI_PLAY_PARMS mciPlayParms; + MCI_STATUS_PARMS mciStatusParms; + MCI_SEQ_SET_PARMS mciSeqSetParms; + + mciOpenParms.lpstrDeviceType = "sequencer"; + mciOpenParms.lpstrElementName = s; + if (dwReturn = mciSendCommand((UINT)NULL, MCI_OPEN, + MCI_OPEN_TYPE | MCI_OPEN_ELEMENT, + (DWORD)(LPVOID) &mciOpenParms)) { + return dwReturn; + } + wDeviceID = mciOpenParms.wDeviceID; + + /* attempt to select the MIDI mapper */ + mciSeqSetParms.dwPort = MIDI_MAPPER; + if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SEQ_SET_PORT, + (DWORD)(LPVOID) &mciSeqSetParms)) { + /* could not select the MIDI mapper; play anyway */ + } + + mciPlayParms.dwCallback = (DWORD) hWndNotify; + if (dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY, + (DWORD)(LPVOID) &mciPlayParms)) { + mciSendCommand(wDeviceID, MCI_CLOSE, 0, (DWORD)NULL); + return dwReturn; + } + + return 0L; +} + + +int playmedia(wbp w, char *s) +{ + if (strstr(s, ".wav") || strstr(s, ".WAV")) { + sndPlaySound((LPSTR) s, SND_ASYNC); + return Succeeded; + } + else if (strstr(s, ".mid") || strstr(s, ".MID") || + strstr(s, ".rmi") || strstr(s, ".RMI")) { + if (playMIDIfile(w->window->win, (LPSTR) s) == 0) + return Succeeded; + } + /* + * Interpret as an MCI command string + */ + else { + if (mciSendString(s, NULL, 0, 0L)) return Failed; + return Succeeded; + } +} + +/* + * UpdateCursorPos + */ +void UpdateCursorPos(wsp ws, wcp wc) +{ + if (ISCURSORONW(ws)) { + if (ws->hasCaret) { + } + CreateCaret(ws->iconwin, NULL, FWIDTHC(wc), FHEIGHTC(wc)); + SetCaretBlinkTime(500); + SetCaretPos(ws->x, ws->y - ASCENTC(wc)); + ShowCaret(ws->iconwin); + ws->hasCaret = 1; + } +} + +int resizePixmap(wbp w, int width, int height) + { + HDC hdc, hdc2, hdc3; + HBITMAP newpix, oldpix, oldpix2; + HBRUSH hb; + LOGBRUSH lb; + XRectangle rect; + wsp ws = w->window; + int x = ws->pixwidth, y = ws->pixheight; + if (ISEXPOSED(w)) { + if (ws->pixwidth >= width && ws->pixheight >= height) { + return 1; + } + ws->pixheight = max(ws->pixheight, height); + ws->pixwidth = max(ws->pixwidth, width); + } + else { + ws->pixwidth = width; + ws->pixheight = height; + } + hdc = GetDC(ws->iconwin); + newpix = CreateCompatibleBitmap (hdc, ws->pixwidth, ws->pixheight); + if (ws->pix) { + hdc2 = CreateCompatibleDC(hdc); + oldpix = SelectObject(hdc2, ws->pix); + } + hdc3 = CreateCompatibleDC(hdc); + oldpix2 = SelectObject(hdc3, newpix); + if (palette) { + SelectPalette(hdc, palette, FALSE); + if (ws->pix) SelectPalette(hdc2, palette, FALSE); + SelectPalette(hdc3, palette, FALSE); + RealizePalette(hdc); + if (ws->pix) RealizePalette(hdc2); + RealizePalette(hdc3); + } + lb.lbStyle = BS_SOLID; + lb.lbColor = PALCLR(w->context->bg); + hb = CreateBrushIndirect(&lb); + /* + * initialize the new pixmap, including areas not in the old pixmap. + */ + rect.left = 0; rect.right = ws->pixwidth; + rect.top = 0; rect.bottom = ws->pixheight; + FillRect(hdc3, &rect, hb); + if (ws->win) + FillRect(hdc, &rect, hb); + + if (ws->pix) BitBlt(hdc3, 0, 0, x - 2, y - 1, hdc2, 0, 0, SRCCOPY); + if (ws->win) + BitBlt(hdc, 0, 0, ws->pixwidth, ws->pixheight, hdc3, 0, 0, SRCCOPY); + SelectObject(hdc3, oldpix2); + DeleteDC(hdc3); + if (ws->pix) { + SelectObject(hdc2, oldpix); + DeleteDC(hdc2); + } + ReleaseDC(ws->iconwin, hdc); + if (ws->pix) DeleteObject(ws->pix); + DeleteObject(hb); + ws->pix = newpix; + return 1; + } + +/* + * CreateWinDC - create a device context for drawing on the window + * In addition, select objects specified by flags. + */ +HDC CreateWinDC(wbp w) + { + wsp ws = w->window; + wcp wc = w->context; + HDC hdc = GetDC(ws->iconwin); + if (numColors > 0) { + SelectPalette(hdc, palette, FALSE); +/* UnrealizeObject(palette); */ + RealizePalette(hdc); + if (numRealized < numColors) { + numRealized = numColors; + if (RealizePalette(hdc) == 0) /* noop */; + } + } + SetROP2(hdc, wc->drawop); + if (wc->clipw >= 0){ + SelectClipRgn(hdc, wc->cliprgn); + } + return hdc; + } + +HDC CreatePixDC(wbp w, HDC hdc) + { + wsp ws = w->window; + wcp wc = w->context; + HBITMAP oldpix; + HDC hdc2 = CreateCompatibleDC(hdc); + if (numColors > 0) { + SelectPalette(hdc2, palette, FALSE); + RealizePalette(hdc2); + } +/* ws->initialPix = */ ws->theOldPix = SelectObject(hdc2, ws->pix); + SetROP2(hdc2, wc->drawop); + if (wc->clipw >= 0){ + SelectClipRgn(hdc2, wc->cliprgn); + } + return hdc2; + } + +int dc_maxcharwidth(HDC dc) +{ + int i, m = -1, x; + char s[2]; + s[1] = '\0'; + for (i=0; i<256; i++) { + s[0] = i; + x = dc_textwidth(dc, s, 1); + if (x > m) m = x; + } + return m; +} + +/* + * compute a text width for a current device context (typically pixdc) + */ +int dc_textwidth(HDC dc, char *s, int n) +{ + SIZE sz; + /* + * GetTextExtentPoint32(dc, s, n, &sz) gives incorrect behavior + * under Win32s + */ + GetTextExtentPoint(dc, s, n, &sz); + return (int)sz.cx; +} + +int sysScrollWidth() +{ + return GetSystemMetrics(SM_CXVSCROLL); +} + +int sysFontHeight(wbp w) +{ + TEXTMETRIC tm; + int rv; + wsp ws = w->window; + HDC dc = GetDC(ws->iconwin); + HFONT oldfont = SelectObject(dc, GetStockObject(SYSTEM_FIXED_FONT)); + GetTextMetrics(dc, &tm); + SelectObject(dc, oldfont); + ReleaseDC(ws->iconwin, dc); + return tm.tmHeight + tm.tmExternalLeading; +} + +int sysTextWidth(wbp w, char *s, int n) +{ + int rv; + wsp ws = w->window; + HDC dc = GetDC(ws->iconwin); + HFONT oldfont; + oldfont = SelectObject(dc, GetStockObject(SYSTEM_FIXED_FONT)); + rv = dc_textwidth(dc, s, n); + SelectObject(dc, oldfont); + ReleaseDC(ws->iconwin, dc); + return rv; +} + +int textWidth(wbp w, char *s, int n) + { + int rv; + wsp ws = w->window; + HDC stddc = GetDC(ws->iconwin); + HFONT oldfont = SelectObject(stddc, w->context->font->font); + rv = dc_textwidth(stddc, s, n); + SelectObject(stddc, oldfont); + ReleaseDC(ws->iconwin, stddc); + return rv; + } + +void warpPointer(w, x, y) +wbp w; +int x, y; + { + wsp ws = w->window; + SetCursorPos(ws->posx + x, ws->posy + y); + } + +/* + * free all Windows resources allocated by this instantiation of iconx + */ +void wfreersc() +{ + wbp w; + extern struct palentry *palsetup_palette; + while (wbndngs != NULL) { + w = wbndngs; + wbndngs = wbndngs->next; + free(w); + } + while (wstates != NULL) { + wstates->refcount = 1; + free_window(wstates); + } + while (wcntxts != NULL) { + wcntxts->refcount = 1; + free_context(wcntxts); + } + if (palette) { + DeleteObject(palette); + palette = 0; + } + if (palsetup_palette) { + free(palsetup_palette); + palsetup_palette = 0; + } + if (scp) { + free(scp); + scp = 0; + } + if (wlhead) + wlfree(); + mciSendCommand(MCI_ALL_DEVICE_ID, MCI_CLOSE, 0, (DWORD)NULL); +} + + +/* + * Native Windows UI facilities + */ +void makebutton(wsp ws, childcontrol *cc, char *s) +{ + cc->type = CHILD_BUTTON; + cc->font = 0; + cc->id = salloc(s); + cc->win = CreateWindow("button", cc->id, + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + 0, 0, 0, 0, ws->iconwin, (HMENU)ws->nChildren, mswinInstance, + NULL); +} + +void makescrollbar(wsp ws, childcontrol *cc, char *s, int i1, int i2) +{ + cc->type = CHILD_SCROLLBAR; + cc->id = salloc(s); + cc->font = 0; + cc->win = CreateWindow("scrollbar", cc->id, + WS_CHILD | WS_VISIBLE | SBS_VERT, 0, 0, 0, 0, + ws->iconwin, (HMENU)ws->nChildren, mswinInstance, NULL); + SetScrollRange(cc->win, SB_CTL, i1, i2, FALSE); +} + +int nativemenubar(wbp w, int total, int argc, dptr argv, int warg, dptr d) +{ + wsp ws; + tended struct b_list *hp; + HMENU tempMenu, tempMenu2 = NULL; + tended char *s, *s2; + int r, i; + ws = w->window; + + if (ws->nmMapElems) + tempMenu2 = ws->menuBar; + + ws->menuBar = CreateMenu(); + ws->nmMapElems = total; + total = 0; + while (warg < argc){ + /* + * each argument must be a list of strings + */ + hp = (struct b_list *)BlkLoc(argv[warg]); + r = hp->size; + /* + * Construct a Windows menu corresponding to the Icon list + */ + tempMenu = CreateMenu(); + for(i=0; i < r; i++) { + c_get(hp, d); + if (!is:string(*d)) return Error; + if (!cnv:C_string(*d, s)) return Error; + s = strdup(s); + if (i == 0) s2=s; + else + AppendMenu(tempMenu, MF_STRING, total, s); + ws->menuMap[total++] = s; + c_put(&(argv[warg]), d); + } + AppendMenu(ws->menuBar, MF_POPUP, (unsigned int)tempMenu, s2); + warg++; + } + /* + * Insert the menu into the window + */ + if (ws->win) SetMenu(ws->win, ws->menuBar); + if (tempMenu2) { + int i, n = GetMenuItemCount(tempMenu2); + for (i=0; i < n; i++) { + DestroyMenu(GetSubMenu(tempMenu2, i)); + } + DestroyMenu(tempMenu2); + } + return Succeeded; +} + +void makeeditregion(wbp w, childcontrol *cc, char *s) +{ + wsp ws = w->window; + cc->type = CHILD_EDIT; + cc->id = salloc(s); + cc->win = CreateWindow("edit", NULL, + WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | + WS_BORDER | ES_LEFT | ES_MULTILINE | + ES_AUTOHSCROLL | ES_AUTOVSCROLL, + 0, 0, 0, 0, ws->iconwin, + (HMENU) ws->nChildren, mswinInstance, NULL); + setchildfont(cc, w->context->font->name); +} + +void cleareditregion(childcontrol *cc) +{ + SendMessage(cc->win, WM_CLEAR, 0, 0); +} + +void copyeditregion(childcontrol *cc) +{ + SendMessage(cc->win, WM_COPY, 0, 0); +} + +void cuteditregion(childcontrol *cc) +{ + SendMessage(cc->win, WM_CUT, 0, 0); +} + +void pasteeditregion(childcontrol *cc) +{ + SendMessage(cc->win, WM_PASTE, 0, 0); +} + +int undoeditregion(childcontrol *cc) +{ + if (!SendMessage(cc->win, WM_UNDO, 0, 0)) return Failed; + return Succeeded; +} + +int modifiededitregion(childcontrol *cc) +{ + if (!SendMessage(cc->win, EM_GETMODIFY, 0, 0)) return Failed; + return Succeeded; +} + +int setmodifiededitregion(childcontrol *cc, int i) +{ + SendMessage(cc->win, EM_SETMODIFY, i, 0); + return Succeeded; +} + +void geteditregion(childcontrol *cc, dptr d) +{ + int y = GetWindowTextLength(cc->win); + char *s2 = alcstr(NULL, y + 1); + GetWindowText(cc->win, s2, y+1); + StrLoc(*d) = s2; + StrLen(*d) = y; +} + +void seteditregion(childcontrol *cc, char *s2) +{ + SetWindowText(cc->win, s2); +} + + +void movechild(childcontrol *cc, + C_integer x, C_integer y, C_integer width, C_integer height) +{ + MoveWindow(cc->win, x, y, width, height, TRUE); +} + +int setchildfont(childcontrol *cc, char *fontname) +{ + HFONT hf; + RECT rect; + if (hf = mkfont(fontname)) { + SendMessage(cc->win, WM_SETFONT, (WPARAM)hf, 0); + if (cc->font) DeleteObject(cc->font); + cc->font = hf; + GetClientRect(cc->win, &rect); + InvalidateRect(cc->win, &rect, TRUE); + return Succeeded; + } + return Failed; +} + +void setfocusonchild(wsp ws, childcontrol *cc, int width, int height) +{ + if (width || height) { + SetFocus(cc->win); + ws->focusChild = cc->win; + } + else ws->focusChild = 0; +} + +void setchildselection(wsp ws, childcontrol *cc, int x, int y) +{ + int iLine = SendMessage(cc->win, EM_LINEFROMCHAR, x-1,0); + int topLine = SendMessage(cc->win, EM_GETFIRSTVISIBLELINE, 0, 0); + if (topLine != iLine) { + SendMessage(cc->win, EM_LINESCROLL, 0, iLine-topLine); + } + SendMessage(cc->win, EM_SETSEL, x - 1, y - 1); + SetFocus(cc->win); + ws->focusChild = cc->win; +} + +CHOOSEFONT cf; +LOGFONT lf; + +int nativefontdialog(wbp w, char *buf, int flags, int fheight) +{ + strcpy(lf.lfFaceName, buf); + lf.lfHeight = fheight; + lf.lfWidth = 0; + lf.lfEscapement = 0; + if (!strcmp(lf.lfFaceName, "mono") || !strcmp(lf.lfFaceName, "fixed")){ + strcpy(lf.lfFaceName, "Lucida Sans Typewriter"); + flags |= FONTFLAG_MONO + FONTFLAG_SANS; + } + else if (!strcmp(lf.lfFaceName, "typewriter")) { + strcpy(lf.lfFaceName, "courier"); + flags |= FONTFLAG_MONO + FONTFLAG_SERIF; + } + else if (!strcmp(lf.lfFaceName, "sans")) { + strcpy(lf.lfFaceName, "swiss"); + flags |= FONTFLAG_PROPORTIONAL + FONTFLAG_SANS; + } + else if (!strcmp(lf.lfFaceName, "serif")) { + strcpy(lf.lfFaceName, "roman"); + flags |= FONTFLAG_PROPORTIONAL + FONTFLAG_SERIF; + } + + if (flags & FONTFLAG_BOLD) lf.lfWeight = FW_BOLD; + else + lf.lfWeight = FW_DONTCARE; + if (flags & FONTFLAG_ITALIC) lf.lfItalic = 1; + lf.lfUnderline = lf.lfStrikeOut = 0; + lf.lfCharSet = + ((MAXBYTESPERCHAR==1)?ANSI_CHARSET:DEFAULT_CHARSET); + lf.lfOutPrecision = OUT_DEFAULT_PRECIS; + lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf.lfQuality = DEFAULT_QUALITY; + if (FONTFLAG_PROPORTIONAL) + lf.lfPitchAndFamily = VARIABLE_PITCH; + else if (FONTFLAG_MONO) + lf.lfPitchAndFamily = FIXED_PITCH; + else + lf.lfPitchAndFamily = DEFAULT_PITCH; + if (!strcmp(lf.lfFaceName, "swiss")) lf.lfPitchAndFamily |= FF_SWISS; + else if (!strcmp(lf.lfFaceName, "roman")) + lf.lfPitchAndFamily |= FF_ROMAN; + else + lf.lfPitchAndFamily |= FF_DONTCARE; + + memset(&cf, 0, sizeof(CHOOSEFONT)); + cf.lStructSize = sizeof(CHOOSEFONT); + cf.hwndOwner = w->window->iconwin; + cf.lpLogFont = &lf; + cf.Flags = CF_SCREENFONTS | CF_EFFECTS | CF_INITTOLOGFONTSTRUCT; + cf.rgbColors = RGB(0,0,0); + cf.nFontType = SCREEN_FONTTYPE; + if (ChooseFont(&cf) == 0) return Failed; + sprintf(buf, "%s,%d%s%s", lf.lfFaceName, + ((lf.lfHeight > 0) ? lf.lfHeight : -lf.lfHeight), + (lf.lfItalic ? ",italic" : ""), + ((lf.lfWeight > 500) ? ",bold" : "")); + return Succeeded; +} + +/* + * common dialog functions + */ +COLORREF aclrCust[16]; +CHOOSECOLOR cc; + +char *nativecolordialog(wbp w, long r, long g, long b, char *buf) +{ + aclrCust[0] = RGB(255,255,255); + aclrCust[1] = RGB(239,239,239); + aclrCust[2] = RGB(223,223,223); + aclrCust[3] = RGB(207,207,207); + aclrCust[4] = RGB(191,191,191); + aclrCust[5] = RGB(175,175,175); + aclrCust[6] = RGB(159,159,159); + aclrCust[7] = RGB(143,143,143); + aclrCust[8] = RGB(127,127,127); + aclrCust[9] = RGB(111,111,111); + aclrCust[10] = RGB(95,95,95); + aclrCust[11] = RGB(79,79,79); + aclrCust[12] = RGB(63,63,63); + aclrCust[13] = RGB(47,47,47); + aclrCust[14] = RGB(31,31,31); + aclrCust[15] = RGB(15,15,15); + memset(&cc, 0, sizeof(CHOOSECOLOR)); + cc.lStructSize = sizeof(CHOOSECOLOR); + cc.hwndOwner = w->window->iconwin; + cc.lpCustColors = aclrCust; + cc.rgbResult = mscolor(w, r, g, b); + cc.Flags = CC_FULLOPEN | CC_RGBINIT; + if (ChooseColor(&cc) == 0) { + return NULL; + } + sprintf(buf, "%d,%d,%d", (RED(cc.rgbResult)<<8) | 0xFF, + (GREEN(cc.rgbResult) << 8) | 0xFF, + (BLUE(cc.rgbResult) << 8) | 0xFF); + return buf; +} + + + + +char *nativeselectdialog(wbp w, struct b_list *L, char *s) +{ + int i, j, okflag=0, yesnoflag=0, cancelflag=0, retryflag=0, otherflag=0; + tended struct b_list *hp = L; + tended char *s1 = NULL; + tended struct descrip d, d2; + char s3[8]; + wsp ws = w->window; + int lsize; + + if (hp == NULL) { + okflag = 1; + } + else { + BlkLoc(d2) = (union block *)hp; + d2.dword = D_List; + lsize = hp->size; + + for(i=0; i < lsize; i++) { + c_get(hp, &d); + if (!cnv:C_string(d, s1)) return NULL; + for(j=0; j<8; j++) { + s3[j] = tolower(s1[j]); + if (s3[j] == '\0') break; + } + if (!strcmp(s3, "ok")) okflag = 1; + else if (!strcmp(s3, "okay")) okflag = 1; + else if (!strcmp(s3, "no")) yesnoflag = MB_YESNO; + else if (!strcmp(s3, "yes")) yesnoflag = MB_YESNO; + else if (!strcmp(s3, "cancel")) cancelflag++; + else if (!strcmp(s3, "retry")) retryflag = MB_RETRYCANCEL; + else { otherflag++; return NULL; } + c_put(&d2, &d); + } + } + /* + * validate flags + */ + if (okflag && yesnoflag) return NULL; + if (okflag && retryflag) return NULL; + if (yesnoflag && retryflag) return NULL; + if (retryflag && !cancelflag) return NULL; + + if (cancelflag) { + if (okflag) { + okflag = MB_OKCANCEL; + } + else if (yesnoflag) yesnoflag = MB_YESNOCANCEL; + } + else if (okflag) okflag = MB_OK; + + j = MessageBox((ws->focusChild ? ws->focusChild : + (ws->win ? ws->win : ws->iconwin)), + s, " ", + okflag | yesnoflag | retryflag + | (strchr(s, '!') ? MB_ICONEXCLAMATION : + (strchr(s, '?') ? MB_ICONQUESTION : MB_ICONASTERISK))); + + switch (j) { + case IDOK: return "Okay"; + case IDCANCEL: return "Cancel"; + case IDYES: return "Yes"; + case IDNO: return "No"; + case IDRETRY: return "Retry"; + default: return NULL; + } +} + +OPENFILENAME ofn; + +char *nativeopendialog(wbp w, char *s1, char *s2, char *s3, int i, int j) +{ + char buf[128], buf2[64]; + + memset(&ofn, 0, sizeof(OPENFILENAME)); + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = w->window->iconwin; + ofn.lpstrFilter = s3; + ofn.nFilterIndex = j; + strcpy(buf, s2); + ofn.lpstrFile = buf; + ofn.nMaxFile = sizeof(buf); + ofn.lpstrTitle = s1; + ofn.lpstrFileTitle = buf2; + ofn.nMaxFileTitle = sizeof(buf2); + ofn.lpstrInitialDir = NULL; + ofn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST; + if (GetOpenFileName(&ofn) == 0) return NULL; + return ofn.lpstrFile; +} + + +char *nativesavedialog(wbp w, char *s1, char *s2, char *s3, int i, int j) +{ + char buf[128], buf2[64]; + /* + * Use the standard dialog to obtain a filename. + */ + memset(&ofn, 0, sizeof(OPENFILENAME)); + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = w->window->iconwin; + ofn.lpstrFilter = s3; + ofn.nFilterIndex = j; + strcpy(buf, s2); + ofn.lpstrFile = buf; + ofn.nMaxFile = sizeof(buf); + ofn.lpstrTitle = s1; + ofn.lpstrFileTitle = buf2; + ofn.nMaxFileTitle = sizeof(buf2); + ofn.lpstrInitialDir = NULL; + ofn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST; + if (GetSaveFileName(&ofn) == 0) return NULL; + return ofn.lpstrFile; +} + +/* + * flush a window - noop under Windows + */ +void wflush(w) +wbp w; + { + } + +#endif /* Graphics */ |