home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v941.tgz / icon.v941src.tar / icon.v941src / src / runtime / rmswin.ri < prev    next >
Text File  |  2002-01-18  |  108KB  |  4,371 lines

  1. /*
  2.  * rmswin.ri - Microsoft Windows-specific graphics interface code.
  3.  *
  4.  * Todo:
  5.  *   geticonpos
  6.  *   seticonimage
  7.  *   free_mutable
  8.  *   freecolor
  9.  *
  10.  * Untested:
  11.  *   toggle_fgbg
  12.  *   rebind
  13.  *   geticonic
  14.  *   getimstr
  15.  *   getfntnam
  16.  *   dumpimage
  17.  *   getpointername
  18.  *
  19.  * Blown off:
  20.  *   getvisual
  21.  *   getdefault
  22.  */
  23. #ifdef Graphics
  24.  
  25. void wfreersc();
  26. int alc_rgb(wbp w, SysColor rgb);
  27. int numRealized;
  28.  
  29. #ifndef min
  30. #define min(x,y) (((x) < (y))?(x):(y))
  31. #define max(x,y) (((x) > (y))?(x):(y))
  32. #endif                                  /* min */
  33. #define PALCLR(c) (c | 0x2000000L)
  34.  
  35. int winInitialized = 0;
  36. int BORDHEIGHT;
  37. int BORDWIDTH;
  38. /*
  39.  * check for double-byte character set versions of Windows
  40.  */
  41. CPINFO cpinfo;
  42. int MAXBYTESPERCHAR;
  43.  
  44. wclrp scp;
  45. HPALETTE palette;
  46. int numColors = 0;
  47.  
  48. char szAppName[] = "Icon";
  49.  
  50. /*
  51.  * pattern symbols
  52.  */
  53. stringint siPatternSyms[] = {
  54.   {0,           16},
  55.   { "black",     0},
  56.   { "checkers",  12},
  57.   { "darkgray",  2},
  58.   { "diagonal",  8},
  59.   { "grains",    13},
  60.   { "gray",      3},
  61.   { "grid",      10},
  62.   { "horizontal",9},
  63.   { "lightgray", 4},
  64.   { "scales",    14},
  65.   { "trellis",   11},
  66.   { "vertical",  7},
  67.   { "verydark",  1},
  68.   { "verylight", 5},
  69.   { "waves",     15},
  70.   { "white",     6},
  71. };
  72.  
  73. /*
  74.  * draw ops
  75.  */
  76. stringint drawops[] = {
  77.    { 0, 16},
  78.    {"and",              R2_MASKPEN},
  79.    {"andInverted",      R2_MASKPENNOT},
  80.    {"andReverse",       R2_MASKNOTPEN},
  81.    {"clear",            R2_BLACK},
  82.    {"copy",             R2_COPYPEN},
  83.    {"copyInverted",     R2_NOTCOPYPEN},
  84.    {"equiv",            R2_NOTXORPEN},
  85.    {"invert",           R2_NOT},
  86.    {"nand",             R2_NOTMASKPEN},
  87.    {"noop",             R2_NOP},
  88.    {"nor",              R2_NOTMERGEPEN},
  89.    {"or",               R2_MERGEPEN},
  90.    {"orInverted",       R2_MERGEPENNOT},
  91.    {"orReverse",        R2_MERGENOTPEN},
  92.    {"set",              R2_WHITE},
  93.    {"xor",              R2_XORPEN},
  94. };
  95.  
  96. /*
  97.  * line types
  98.  */
  99. stringint siLineTypes[] = {
  100.   {0, 6},
  101.   {"dashdotted",        PS_DASHDOT},
  102.   {"dashdotdotted",     PS_DASHDOTDOT},
  103.   {"dashed",            PS_DOT},
  104.   {"longdashed",        PS_DASH},
  105.   {"solid",             PS_SOLID},
  106.   {"striped",           PS_DOT}
  107. };
  108.  
  109. HINSTANCE mswinInstance;
  110. int ncmdShow;
  111.  
  112. int FoundIt, FoundNew;
  113. HWND NewWin;
  114. char *lookingfor;
  115. struct WNDlist {
  116.    HWND w;
  117.    struct WNDlist *next;
  118.    } * wlhead;
  119.  
  120. struct WNDlist *wlinsert(HWND w)
  121. {
  122.    struct WNDlist *x = malloc(sizeof (struct WNDlist));
  123.    x->w = w;
  124.    x->next = wlhead;
  125.    wlhead = x;
  126. }
  127.  
  128. int wlsearch(HWND w)
  129. {
  130.    struct WNDlist *x;
  131.    for(x=wlhead;x;x=x->next) if (x->w == w) return 1;
  132.    return 0;
  133. }
  134.  
  135. void wlfree()
  136. {
  137.    struct WNDlist *x = wlhead;
  138.    while (wlhead) {
  139.       x = wlhead->next;
  140.       free(wlhead);
  141.       wlhead = x;
  142.       }
  143. }
  144.  
  145. BOOL_CALLBACK myenumproc(HWND w, LPARAM l)
  146. {
  147.    wlinsert(w);
  148.    return 1;
  149. }
  150.  
  151. BOOL_CALLBACK myenumproc2(HWND w, LPARAM l)
  152. {
  153.    if (!wlsearch(w)) {
  154.       FoundNew++;
  155.       NewWin = w;
  156.       }
  157.    return 1;
  158. }
  159.  
  160. char * strcasestr(char *haystack, char *needle)
  161. {
  162.    int len = strlen(needle);
  163.    while (*haystack) {
  164.       if (strncasecmp(haystack, needle, len) == 0) return haystack;
  165.       haystack++;
  166.       }
  167.    return 0;
  168. }
  169.  
  170. BOOL_CALLBACK myenumproc3(HWND w, LPARAM l)
  171. {
  172.    char s[64], s2[64];
  173.    GetWindowText(w, s2, 63);
  174.    /*
  175.     * Conditions to find a window:
  176.     * 1) wasn't in the list of windows already present when we launched.
  177.     * 2) either contains the argv[0] program name, or
  178.     *    was first window to appear after we called WinExec().
  179.     */
  180.    if (!wlsearch(w)) {
  181.       FoundNew++;
  182.       if ((strcasestr(s2, lookingfor) != NULL) || (NewWin && (NewWin == w))) {
  183.          FoundIt++;
  184.          }
  185.       }
  186.    return 1;
  187. }
  188.  
  189. char *lookcmdname(char *buf, char *s)
  190. {
  191.   char *t = buf;
  192.   while (*s) {
  193.     *t++ = *s;
  194.     if (*s == '\\') t = buf;
  195.     s++;
  196.     }
  197.   *t++ = '\0';
  198.   s = buf;
  199.   while (*s) {
  200.     if (*s == '.') *s = '\0';
  201.     s++;
  202.     }
  203.   return buf;
  204. }
  205.  
  206. int mswinsystem(char *s)
  207. {
  208.    int i, rv, j, background = 0;
  209.    char s2[256], s3[256];
  210.    char **argv;
  211.    int argc;
  212.  
  213.    DWORD d  = GetVersion();
  214.    int lo, hi, major, minor, iswin31;
  215.    lo = LOWORD(d);
  216.    hi = HIWORD(d);
  217.    major = lo & 0xFF;
  218.    minor = (lo & 0xFF00)>>8,
  219.    iswin31 = ((major == 3) && (minor <= 11));
  220.  
  221.    strncpy(s2, s, 255);
  222.    s2[255] = '\0';
  223.  
  224.    strncpy(s3, s, 255);
  225.    s3[255] = '\0';
  226.    for(i=0;s3[i];i++){
  227.       if (s3[i] == ' ' || s3[i] == '\t') {
  228.          s3[i] = '\0';
  229.          break;
  230.          }
  231.       }
  232.  
  233.    for(i=strlen(s2)-1; i > 0 && (s2[i] == ' ' || s2[i] == '\t'); i--);
  234.  
  235.    /*
  236.     * if it is a "background task", launch using WinExec.
  237.     */
  238.    if (i>0 && s2[i] == '&') {
  239.       s2[i] = '\0';
  240.       while (s2[--i] == ' ') s2[i] = '\0';
  241.       i = WinExec(s2, SW_SHOW);
  242.       if ( i >= 32 ) return 0;
  243.       return -1;
  244.       }
  245.  
  246.    /*
  247.     * if we've got a reasonable operating system, launch using spawnvp
  248.     * and wait for _P_WAIT.  At the moment, this gives no indication of
  249.     * actually working; the program is launched but we don't wait for it.
  250.     */
  251.    if (!iswin31) {
  252.       argc = CmdParamToArgv(s, &argv);
  253.       rv = _spawnvp(_P_WAIT, s3, argv);
  254.       free(argv);
  255.       return rv;
  256.       }
  257.  
  258.    /*
  259.     * this remaining code is a colossal kludge to support waiting for
  260.     * a launched application to terminate under Win32s, which ignores
  261.     * the _P_WAIT flag to the spawn* functions.
  262.     */
  263.  
  264.    for(i=0;s2[i];i++){
  265.       if (s2[i] == ' ' || s2[i] == '\t' || s2[i] == '.') {
  266.          s2[i] = '\0';
  267.          break;
  268.          }
  269.       }
  270.    wlfree();
  271.    lookingfor = NULL;
  272.    EnumWindows(MakeProcInstance(myenumproc, mswinInstance), 0L);
  273.    i = WinExec(s, SW_SHOW);
  274.    if ( i >= 32 ) {
  275.       /*
  276.        * Wait for the task to finish.  First wait up to two seconds
  277.        *  for at least one new window to show up.
  278.        */
  279.       lookcmdname(s3, s2);
  280.       lookingfor = s3;
  281.       FoundNew = 0;
  282.       for(j=0; j<10; j++) {
  283.          EnumWindows(MakeProcInstance(myenumproc2, mswinInstance), 0L);
  284.          if (FoundNew) break;
  285.          Sleep(200);
  286.          }
  287.       if (FoundNew != 1) NewWin = NULL;
  288.       /*
  289.        * Now wait as long as we found a new window with our
  290.        * argv[0] in its title present.
  291.        */
  292.       for(;;) {
  293.          FoundIt = 0;
  294.          EnumWindows(MakeProcInstance(myenumproc3, mswinInstance), 0L);
  295.          if(!FoundIt) break;
  296.          Sleep(10);
  297.          pollevent();
  298.          }
  299.       return 0;
  300.       }
  301.    else return -1;
  302.  
  303. }
  304.  
  305.  
  306. /*
  307.  * wopen
  308.  */
  309. FILE *wopen(char *name, struct b_list *lp, dptr attr, int n, int *err_idx)
  310.    {
  311.    wbp w;
  312.    wsp ws;
  313.    wcp wc;
  314.    struct imgdata *imd;
  315.    char answer[256];
  316.    int i, r;
  317.    tended struct b_list *tlp;
  318.    tended struct descrip attrrslt;
  319.    HDC hdc, hdc2, hdc3;
  320.    TEXTMETRIC    metrics;
  321.    LOGPALETTE logpal[4]; /* really 1 + space for an extra palette entry */
  322.    HBRUSH brush;
  323.    HBITMAP oldpix, oldpix2;
  324.    HFONT oldfont;
  325.  
  326.    if (! winInitialized++) {
  327.       BORDWIDTH = FRAMEWIDTH * 2;
  328.       BORDHEIGHT = TITLEHEIGHT + FRAMEHEIGHT * 2 - 1;
  329.       GetCPInfo(CP_ACP, &cpinfo);
  330.       MAXBYTESPERCHAR = cpinfo.MaxCharSize;
  331.       }
  332.  
  333.    tlp = lp;
  334.  
  335.    /*
  336.     * allocate a binding, a window state, and a context
  337.     */
  338.    Protect(w = alc_wbinding(), return NULL);
  339.    Protect(w->window = alc_winstate(), { free_binding(w); return NULL; });
  340.    Protect(w->context = alc_context(w), { free_binding(w); return NULL; });
  341.    ws = w->window;
  342.    ws->listp.dword = D_List;
  343.    BlkLoc(ws->listp) = (union block *)lp;
  344.    ws->width = ws->height = 0;
  345.    wc = w->context;
  346.  
  347.    /*
  348.     * process the passed in attributes - by calling wattrib
  349.     */
  350.    for(i = 0; i < n; i++)
  351.       switch (wattrib(w, StrLoc(attr[i]), StrLen(attr[i]), &attrrslt,
  352.             answer)) {
  353.       case Failed:
  354.      wclose(w);
  355.      return NULL;
  356.       case Error:
  357.      /* think of something to do here */
  358.      break;
  359.      }
  360.  
  361.    /*
  362.     * set the title, defaulting to the "filename" supplied to open()
  363.     */
  364.    if (ws->windowlabel == NULL) ws->windowlabel = salloc(name);
  365.    if (ws->iconlabel == NULL) ws->iconlabel = salloc(name);
  366.  
  367.    if (ws->posx < 0) ws->posx = 0;
  368.    if (ws->posy < 0) ws->posy = 0;
  369.  
  370.    /*
  371.     * create the window
  372.     */
  373.    ws->iconwin = CreateWindow( "iconx", ws->windowlabel, WS_OVERLAPPEDWINDOW,
  374.            ws->posx, ws->posy,
  375.            ws->width == 0 ? 400 : ws->width + BORDWIDTH,
  376.            ws->height == 0 ? 400: ws->height + BORDHEIGHT,
  377.            NULL, NULL, mswinInstance, NULL);
  378.    hdc = GetDC(ws->iconwin);
  379.    if ((GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) && (numColors == 0)){
  380.       /* This window is on a device that supports palettes */
  381.       numColors = 2;
  382.       logpal[0].palNumEntries = 2;
  383.       logpal[0].palVersion = 0x300;
  384.       logpal[0].palPalEntry[0].peFlags = 0;
  385.       logpal[0].palPalEntry[0].peRed = 0;
  386.       logpal[0].palPalEntry[0].peGreen = 0;
  387.       logpal[0].palPalEntry[0].peBlue = 0;
  388.       logpal[0].palPalEntry[1].peFlags = 0;
  389.       logpal[0].palPalEntry[1].peRed = 255;
  390.       logpal[0].palPalEntry[1].peGreen = 255;
  391.       logpal[0].palPalEntry[1].peBlue = 255;
  392.       palette = CreatePalette(logpal);
  393.       if ((scp = malloc(2 * sizeof (struct wcolor))) == NULL) return NULL;
  394.       scp[0].c = RGB(0,0,0);
  395.       scp[0].type = SHARED;
  396.       strcpy(scp[0].name, "black");
  397.       scp[1].c = RGB(255,255,255);
  398.       scp[1].type = SHARED;
  399.       strcpy(scp[1].name, "white");
  400.       }
  401.    oldfont = SelectObject(hdc, wc->font->font);
  402.    GetTextMetrics(hdc, &metrics);
  403.    wc->font->charwidth = dc_maxcharwidth(hdc);
  404.    SelectObject(hdc, oldfont);
  405.    ReleaseDC(ws->iconwin, hdc);
  406.    wc->font->ascent = metrics.tmAscent;
  407.    wc->font->descent = metrics.tmDescent;
  408.    /*   wc->font->charwidth = metrics.tmMaxCharWidth; buggy */
  409.    wc->font->height = metrics.tmHeight;
  410.    wc->leading = metrics.tmHeight;
  411.    ws->x = 0;
  412.    ws->y = ASCENT(w);
  413.    ws->y += w->context->dy;
  414.    ws->x += w->context->dx;
  415.    /*
  416.     * set the generic window's true default sizes
  417.     */
  418.    if (!ws->width || !ws->height) {
  419.       if (!ws->width) ws->width = FWIDTH(w) * 80;
  420.       if (!ws->height) ws->height = FHEIGHT(w) * 12;
  421.       SetWindowPos(ws->iconwin, ws->iconwin,
  422.            ws->posx,
  423.            ws->posy,
  424.            ws->width + BORDWIDTH, ws->height + BORDHEIGHT,
  425.            SWP_NOZORDER);
  426.       }
  427.    if (!ws->pix) {
  428.       hdc = GetDC(ws->iconwin);
  429.       ws->pix = CreateCompatibleBitmap(hdc, ws->width, ws->height);
  430.       ReleaseDC(ws->iconwin, hdc);
  431.       }
  432.  
  433.    if (alc_rgb(w, wc->fg) == Failed) {
  434.       return 0;
  435.       }
  436.    if (alc_rgb(w, wc->bg) == Failed) {
  437.       return 0;
  438.       }
  439.    ws->pixwidth = ws->width;
  440.    ws->pixheight = ws->height;
  441.    if (!ISTOBEHIDDEN(ws)) {
  442.       ws->win = ws->iconwin;
  443.       ShowWindow(ws->win, ncmdShow);
  444.       }
  445.    else ws->win = 0;
  446.  
  447.    if (ws->initialPix) {
  448.       hdc = GetDC(ws->iconwin);
  449.       hdc2 = CreateCompatibleDC(hdc);
  450.       oldpix = SelectObject(hdc2, ws->pix);
  451.       hdc3 = CreateCompatibleDC(hdc);
  452.       oldpix2 = SelectObject(hdc3, ws->initialPix);
  453.       BitBlt(hdc2, 0, 0, ws->width, ws->height, hdc3, 0, 0, SRCCOPY);
  454.       if (ws->win)
  455.          BitBlt(hdc, 0, 0, ws->width, ws->height, hdc3, 0, 0, SRCCOPY);
  456.       SelectObject(hdc2, oldpix);
  457.       SelectObject(hdc3, oldpix2);
  458.       DeleteDC(hdc2);
  459.       DeleteDC(hdc3);
  460.       DeleteObject(ws->initialPix);
  461.       ws->initialPix = (HBITMAP) NULL;
  462.       }
  463.    else {
  464.       /*
  465.        * initialize the image with the background color
  466.        */
  467.       RECT rec;
  468.       hdc = GetDC(ws->iconwin);
  469.       hdc2 = CreateCompatibleDC(hdc);
  470.       oldpix = SelectObject(hdc2, ws->pix);
  471.       rec.left = rec.top = 0;
  472.       rec.right = ws->width;
  473.       rec.bottom = ws->height;
  474.       if (palette) {
  475.          SelectPalette(hdc, palette, FALSE);
  476.          SelectPalette(hdc2, palette, FALSE);
  477.      RealizePalette(hdc);
  478.      RealizePalette(hdc2);
  479.      }
  480.       brush = CreateBrushIndirect(&(wc->bgbrush));
  481.       if (ws->win)
  482.          FillRect(hdc, &rec, brush);
  483.       FillRect(hdc2, &rec, brush);
  484.       DeleteObject(brush);
  485.       SelectObject(hdc2, oldpix);
  486.       ReleaseDC(ws->iconwin, hdc);
  487.       DeleteDC(hdc2);
  488.  
  489.       imd = &ws->initimage;
  490.       if (imd->width) {
  491.      r = strimage(w, 0, 0, imd->width, imd->height, imd->paltbl,
  492.               imd->data, (word)imd->width * (word)imd->height, 0);
  493.      free((pointer)imd->paltbl);
  494.      free((pointer)imd->data);
  495.      imd->width = 0;
  496.      if (r < 0) {
  497.         return 0;
  498.         }
  499.      }
  500.       }
  501.    if (ws->win)
  502.       UpdateWindow(ws->win);
  503.  
  504.    return (FILE *)w;
  505.    }
  506.  
  507. int handle_config(wbp w, UINT msg, WPARAM wp, LPARAM lp)
  508.    {
  509.    int neww, newh;
  510.    struct descrip d;
  511.    wsp ws = w->window;
  512.  
  513.    if (wp == SIZE_MINIMIZED) {
  514.       if (ws->win) {
  515.          SetWindowText(ws->win, ws->iconlabel);
  516.          ws->win = NULL;
  517.      }
  518.       return 1;
  519.       }
  520.  
  521.    if (ws->win)
  522.       SetWindowText(ws->win, ws->windowlabel);
  523.    ws->win = ws->iconwin;
  524.  
  525.    /*
  526.     * make sure text cursor stays on-screen
  527.     */
  528.    ws->x = min(ws->x, LOWORD(lp) - FWIDTH(w));
  529.    ws->y = min(ws->y, HIWORD(lp));
  530.  
  531.    neww = LOWORD(lp);
  532.    newh = HIWORD(lp);
  533.  
  534.    /*
  535.     * if it was not a resize, drop it
  536.     */
  537.    if ((ws->width == neww) && (ws->height == newh)) {
  538.       return 1;
  539.       }
  540.  
  541.    ws->width = neww;
  542.    ws->height = newh;
  543.    if (! resizePixmap(w, ws->width, ws->height)) return 0;
  544.    if (!ISEXPOSED(w)) {
  545.       SETEXPOSED(w);
  546.       return 1;
  547.       }
  548.    MakeInt(RESIZED, &d);
  549.    qevent(w->window, &d, ws->width, ws->height, ~(uword)0, 0);
  550.    return 1;
  551.    }
  552.  
  553. /*
  554.  * handle window controls (child windows), at the moment these are
  555.  * buttons and scrollbars.  wp is which child (base 1).
  556.  * Buttons come in as undiluted messages.
  557.  * Scrollbars come in with msg = new value of scrollbar
  558.  */
  559. void handle_child(wbp wb, UINT msg, WPARAM wp, LPARAM lp)
  560.    {
  561.    DWORD dw;
  562.    LONG t;
  563.    WORD x, y;
  564.    wsp ws = wb->window;
  565.    char *s;
  566.    int len;
  567.    struct descrip d;
  568.    int flags = 0;
  569.    if (LOWORD(wp) > ws->nChildren) return;
  570.    s = ws->child[LOWORD(wp) - 1].id;
  571.    len = strlen(s);
  572.    d = nulldesc;
  573.    StrLoc(d) = alcstr(s, len);
  574.    StrLen(d) = len;
  575.    switch (HIWORD(wp)) {
  576.    case BN_CLICKED: {
  577.       dw = GetMessagePos();
  578.       x = LOWORD(dw);
  579.       y = HIWORD(dw);
  580.       break;
  581.       }
  582.    case EN_SETFOCUS: case EN_KILLFOCUS: case EN_CHANGE: case EN_UPDATE:
  583.    case EN_ERRSPACE: case EN_MAXTEXT: case EN_HSCROLL: case EN_VSCROLL: {
  584.     return;
  585.       }
  586.    default: { /* scrollbar */
  587.       x = y = msg;
  588.       }
  589.    }
  590.    t = GetMessageTime();
  591.    qevent(ws, &d, x, y, t, flags);
  592.    if (ws->focusChild)
  593.       SetFocus(ws->focusChild);
  594.    else if (ws->win)
  595.       SetFocus(ws->win);
  596.    else
  597.       SetFocus(ws->iconwin);
  598.    }
  599.  
  600. void handle_menu(wbp wb, UINT msg, WPARAM wp, LPARAM lp)
  601.    {
  602.    wsp ws = wb->window;
  603.    DWORD dw;
  604.    LONG t;
  605.    WORD x, y;
  606.    struct descrip d;
  607.    char *s = ws->menuMap[wp];
  608.    int len = strlen(s);
  609.    int flags = 0;
  610.  
  611.    d = nulldesc;
  612.    StrLoc(d) = alcstr(s, len);
  613.    StrLen(d) = len;
  614.    dw = GetMessagePos();
  615.    x = LOWORD(dw);
  616.    y = HIWORD(dw);
  617.    t = GetMessageTime();
  618.    qevent(ws, &d, x, y, t, flags);
  619.    }
  620.  
  621. void handle_keypress(wbp wb, UINT msg, WPARAM wp, LPARAM lp, int meta)
  622.    {
  623.    wsp ws = wb->window;
  624.    DWORD dw;
  625.    LONG t;
  626.    WORD x, y;
  627.    struct descrip d;
  628.    int flags = 0;
  629.    if (msg == WM_CHAR || msg == WM_SYSCHAR) {
  630.       StrLen(d) = 1;
  631.       StrLoc(d) = (char *)&allchars[wp & 0xFF];
  632.       }
  633.    else { /* WM_KEYDOWN or WM_SYSKEYDOWN */
  634.       MakeInt(wp, &d);
  635.       }
  636.    dw = GetMessagePos();
  637.    x = LOWORD(dw);
  638.    y = HIWORD(dw);
  639.    t = GetMessageTime();
  640.    if (GetKeyState(VK_CONTROL) < 0) flags |= ControlMask;
  641.    if (GetKeyState(VK_SHIFT) < 0) flags |= ShiftMask;
  642.  
  643.    if (meta) flags |= Mod1Mask;
  644.    qevent(ws, &d, x, y, t, flags);
  645.    }
  646.  
  647. void handle_mouse(wbp wb, UINT msg, WPARAM wp, LPARAM lp)
  648.    {
  649.    wsp ws = wb->window;
  650.    LONG t;
  651.    WORD x, y;
  652.    struct descrip d;
  653.    long flags = 0, eventcode;
  654.  
  655.    switch(msg) {
  656.    case WM_MOUSEMOVE: /* only called if one of these three cases is true */
  657.       if (MK_LBUTTON & wp)
  658.      eventcode = MOUSELEFTDRAG;
  659.       else if (MK_RBUTTON & wp)
  660.      eventcode = MOUSERIGHTDRAG;
  661.       else if (MK_MBUTTON & wp)
  662.      eventcode = MOUSEMIDDRAG;
  663.       else eventcode = MOUSEMOVED;
  664.       break;
  665.    case WM_LBUTTONDOWN:
  666.       eventcode = MOUSELEFT;
  667.       break;
  668.    case WM_MBUTTONDOWN:
  669.       eventcode = MOUSEMID;
  670.       break;
  671.    case WM_RBUTTONDOWN:
  672.       eventcode = MOUSERIGHT;
  673.       break;
  674.    case WM_LBUTTONUP:
  675.       eventcode = MOUSELEFTUP;
  676.       break;
  677.    case WM_MBUTTONUP:
  678.       eventcode = MOUSEMIDUP;
  679.       break;
  680.    case WM_RBUTTONUP:
  681.       eventcode = MOUSERIGHTUP;
  682.       break;
  683.       }
  684.  
  685.    MakeInt(eventcode, &d);
  686.    x = LOWORD(lp);
  687.    y = HIWORD(lp);
  688.    t = GetMessageTime(); /* why might someone comment this out? */
  689.  
  690.    if (MK_CONTROL & wp) flags |= ControlMask;
  691.    if (MK_SHIFT & wp) flags |= ShiftMask;
  692.  
  693.    qevent(ws, &d, x, y, t, flags);
  694.    }
  695.  
  696. LRESULT_CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
  697. {
  698.    HDC hdc, hdc2;
  699.    PAINTSTRUCT ps;
  700.    RECT rect;
  701.    wbp wb = NULL;
  702.    wsp ws = NULL;
  703.    int n, i, imin, imax;
  704.  
  705.    /*
  706.     * find a binding associated with the given window.
  707.     */
  708.    for (wb = wbndngs; wb; wb=wb->next) {
  709.       ws = wb->window;
  710.  
  711.       if (((ws->win == hwnd) || (ws->iconwin == hwnd) ||
  712.        (ws->pix == hwnd) || (ws->initialPix == hwnd))) break;
  713.       }
  714.    if (msg == WM_QUIT) {
  715.       extern void closelogfile();
  716.       wfreersc();
  717.       closelogfile();
  718.       }
  719.    else if (!wb) {
  720.       /*
  721.        * doesn't look like its for one of our windows, pass it to
  722.        * DefWindowProc and hope for the best.
  723.        */
  724.       }
  725.    else
  726.    switch(msg) {
  727.    case WM_PAINT:
  728.       hdc = BeginPaint(hwnd, &ps);
  729.       GetClientRect(hwnd, &rect);
  730.       if (IsIconic(hwnd)) {
  731.          HBRUSH hb = CreateBrushIndirect(&(wb->context->brush));
  732.      FrameRect(hdc, &rect, hb);
  733.      DeleteObject(hb);
  734.      DrawText(hdc, "Iconx", 5, &rect, DT_WORDBREAK);
  735.      }
  736.       else {
  737.          HBITMAP oldpix;
  738.      hdc2 = CreateCompatibleDC(hdc);
  739.      oldpix = SelectObject(hdc2, ws->pix);
  740.      BitBlt(hdc, rect.left, rect.top,
  741.         rect.right - rect.left + 1, rect.bottom - rect.top + 1,
  742.         hdc2, rect.left, rect.top, SRCCOPY);
  743.          SelectObject(hdc2, oldpix);
  744.      DeleteDC(hdc2);
  745.      }
  746.       EndPaint(hwnd, &ps);
  747.       return 0;
  748.    case WM_MOUSEMOVE:
  749.       if (ws->curcursor)
  750.          SetCursor(ws->curcursor);
  751.       if ((ws->inputmask & PointerMotionMask) ||
  752.       ((MK_LBUTTON | MK_RBUTTON | MK_MBUTTON) & wp))
  753.      handle_mouse(wb,msg,wp,lp);
  754.       return 0;
  755.    case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: case WM_MBUTTONDOWN:
  756.    case WM_LBUTTONUP:   case WM_RBUTTONUP:   case WM_MBUTTONUP:
  757.       handle_mouse(wb,msg,wp,lp);
  758.       return 0;
  759.    case WM_KEYDOWN:
  760.       switch (wp) { /* VK defn's from <winuser.h> */
  761.       case VK_F1: case VK_F2: case VK_F3: case VK_F4:
  762.       case VK_F5: case VK_F6: case VK_F7: case VK_F8:
  763.       case VK_F9: case VK_F10: case VK_F11: case VK_F12:
  764.       case VK_HOME: case VK_END: case VK_PRIOR: case VK_NEXT:
  765.       case VK_LEFT: case VK_RIGHT: case VK_UP: case VK_DOWN:
  766.       case VK_INSERT: case VK_SELECT: case VK_PRINT:
  767.       case VK_EXECUTE: case VK_SNAPSHOT: case VK_HELP: case VK_SEPARATOR:
  768.       case VK_CLEAR: case VK_PAUSE: case VK_SCROLL:
  769.      handle_keypress(wb, msg, wp, lp, 0);
  770.      return 0;
  771.       case VK_DELETE:
  772.      handle_keypress(wb, WM_CHAR, '\177', lp, 0);
  773.      return 0;
  774.       }
  775.       break;
  776.    case WM_SYSKEYDOWN:
  777.       switch (wp) {
  778.       case VK_F1: case VK_F2: case VK_F3: /* alt-F4 terminates */
  779.       case VK_F5: case VK_F6: case VK_F7: case VK_F8:
  780.       case VK_F9: case VK_F10: case VK_F11: case VK_F12:
  781.       case VK_HOME: case VK_END: case VK_PRIOR: case VK_NEXT:
  782.       case VK_LEFT: case VK_RIGHT: case VK_UP: case VK_DOWN:
  783.       case VK_INSERT: case VK_DELETE: case VK_SELECT: case VK_PRINT:
  784.       case VK_EXECUTE: case VK_SNAPSHOT: case VK_HELP: case VK_SEPARATOR:
  785.       case VK_CLEAR: case VK_PAUSE:
  786.      handle_keypress(wb, msg, wp, lp, 1);
  787.      return 0;
  788.     }
  789.       break;
  790.    case WM_CHAR:
  791.       handle_keypress(wb, msg, wp, lp, 0);
  792.       return 0;
  793.    case WM_SYSCHAR:
  794.       handle_keypress(wb, msg, wp, lp, 1);
  795.       /*
  796.        * Unless there is a menu bar installed,
  797.        * Alt-A .. Alt-Z, and Alt-0 .. Alt-9 are eaten by Icon;
  798.        * others are passed on to Windows for things like Alt-Esc.
  799.        */
  800.       if (isalnum(wp) && !(ws->menuMap)) return 0;
  801.       break;
  802.    case WM_HSCROLL:
  803.    case WM_VSCROLL:
  804.       for(n=0; n < ws->nChildren && ws->child[n].win != (HWND)LOWORD(lp); n++){
  805.          }
  806.       if (n == ws->nChildren) break;
  807.       i = GetScrollPos(ws->child[n].win, SB_CTL);
  808.       GetScrollRange(ws->child[n].win, SB_CTL, &imin, &imax);
  809.       switch (LOWORD(wp)) {
  810.       case SB_PAGEDOWN :
  811.          break;
  812.       case SB_LINEDOWN :
  813.          if (i < imax) {
  814.             SetScrollPos(ws->child[n].win, SB_CTL,
  815.            GetScrollPos(ws->child[n].win, SB_CTL) + 1, TRUE);
  816.         }
  817.          break;
  818.       case SB_PAGEUP :
  819.          break;
  820.       case SB_LINEUP :
  821.          if (i > imin) {
  822.             SetScrollPos(ws->child[n].win, SB_CTL,
  823.            GetScrollPos(ws->child[n].win, SB_CTL) - 1, TRUE);
  824.         }
  825.          break;
  826.       case SB_TOP :
  827.          SetScrollPos(ws->child[n].win, SB_CTL, imin, TRUE);
  828.          break;
  829.       case SB_BOTTOM :
  830.          SetScrollPos(ws->child[n].win, SB_CTL, imax, TRUE);
  831.          break;
  832.       case SB_THUMBPOSITION :
  833.          SetScrollPos(ws->child[n].win, SB_CTL, HIWORD(wp), TRUE);
  834.          break;
  835.       case SB_THUMBTRACK :
  836.          SetScrollPos(ws->child[n].win, SB_CTL, HIWORD(wp), TRUE);
  837.          break;
  838.       case SB_ENDSCROLL: /* noop */
  839.          break;
  840.       default : /* potentially a problem here */
  841.          break;
  842.       }
  843.       i = GetScrollPos(ws->child[n].win, SB_CTL);
  844.       handle_child(wb, i, n+1, -1);
  845.       break;
  846.    case WM_COMMAND:
  847.       if (LOWORD(lp) == 0)
  848.          handle_menu(wb, msg, wp, lp);
  849.       else
  850.          handle_child(wb, msg, wp, lp);
  851.       break;
  852.    case WM_SIZE:
  853.       handle_config(wb, msg, wp, lp);
  854.       break;
  855.    case WM_MOVE:
  856.       ws->posx = LOWORD(lp) - (BORDWIDTH>>1);
  857.       ws->posy = HIWORD(lp) - (BORDHEIGHT - 4);
  858.       break;
  859.    case WM_ACTIVATE:
  860.       if (wp == WA_INACTIVE) {
  861.          if (ws->savedcursor) SetCursor(ws->savedcursor);
  862.          if (ws->hasCaret) {
  863.             HideCaret(ws->iconwin);
  864.             DestroyCaret();
  865.             ws->hasCaret = 0;
  866.             }
  867.          }
  868.       else { /* ... */
  869.          if (ws->savedcursor == NULL)
  870.             ws->savedcursor = SetCursor(ws->curcursor);
  871.          else (void) SetCursor(ws->curcursor);
  872.          if (ISCURSORON(wb)) {
  873.         CreateCaret(ws->iconwin, NULL, FWIDTH(wb), FHEIGHT(wb));
  874.         SetCaretPos(ws->x, ws->y - ASCENT(wb));
  875.         SetCaretBlinkTime(500);
  876.         ShowCaret(ws->iconwin);
  877.         ws->hasCaret = 1;
  878.             }
  879.      }
  880.       break;
  881.    case WM_GETMINMAXINFO: {
  882.       MINMAXINFO *mmi = (MINMAXINFO *)lp;
  883.       if (! ISRESIZABLE(wb)) {
  884.      mmi->ptMinTrackSize.x = mmi->ptMaxTrackSize.x =
  885.         ws->width + BORDWIDTH;
  886.      mmi->ptMinTrackSize.y = mmi->ptMaxTrackSize.y =
  887.         ws->height + BORDHEIGHT;
  888.      }
  889.       return 0;
  890.       }
  891.    case WM_KILLFOCUS:
  892.       if (ws->hasCaret) {
  893.          HideCaret(ws->iconwin);
  894.          DestroyCaret();
  895.          ws->hasCaret = 0;
  896.          }
  897.       break;
  898.    case WM_SETFOCUS:
  899.       if (ws->focusChild)
  900.          SetFocus(ws->focusChild);
  901.       else if (ISCURSORON(wb)) {
  902.      CreateCaret(ws->iconwin, NULL, FWIDTH(wb), FHEIGHT(wb));
  903.      SetCaretPos(ws->x, ws->y - ASCENT(wb));
  904.      SetCaretBlinkTime(500);
  905.      ShowCaret(ws->iconwin);
  906.      ws->hasCaret = 1;
  907.          }
  908.       break;
  909.    /* case WM_QUIT is handled prior to the switch*/
  910.    case WM_DESTROY:
  911.       if (ws->win == hwnd)
  912.      ws->win = NULL;
  913.       if (ws->iconwin == hwnd)
  914.      ws->iconwin = NULL;
  915.       if (ws->refcount > 0) {
  916.          closelogfile();
  917.      PostQuitMessage(0);
  918.      return 0;
  919.      }
  920.       else if (ws->refcount < 0) {
  921.      ws->refcount = -ws->refcount;
  922.      }
  923.       break;
  924.    case WM_MCINOTIFY:
  925.       mciSendCommand(LOWORD(lp), MCI_CLOSE, 0, (DWORD)NULL);
  926.       break;
  927.    }
  928.    return DefWindowProc(hwnd, msg, wp, lp);
  929. }
  930.  
  931. /*
  932.  * wclose - make sure the window goes away - no questions asked
  933.  */
  934. int wclose(wbp w)
  935.    {
  936.    wsp ws = w->window;
  937.    if (pollevent() == -1) return -1;
  938.    if (ws->win && ws->refcount > 1) {
  939.       /*
  940.        * Decrement refcount and negate it to tell the window procedure
  941.        * that we closed the window, not the user, so don't terminate.
  942.        */
  943.       ws->refcount--;
  944.       ws->refcount = -ws->refcount;
  945.       DestroyWindow(ws->win);
  946.       while (ws->win)
  947.      if (pollevent() == -1) return -1;
  948.       }
  949.    else {
  950.       free_binding(w);
  951.       }
  952.    return 1;
  953.    }
  954.  
  955. int pollevent()
  956.    {
  957.    wbp w;
  958.    MSG m;
  959.    extern jmp_buf mark_sj;
  960.  
  961.    /* some while PeekMessage loops here, maybe one per window ? */
  962.    while (PeekMessage(&m, NULL, 0, 0, PM_NOREMOVE)) {
  963.       if (GetMessage(&m, NULL, 0, 0) == 0) longjmp(mark_sj, -1);
  964.       TranslateMessage(&m);
  965.       DispatchMessage(&m);
  966.       }
  967.    return 400;
  968.    }
  969.  
  970. /*
  971.  * write some text to both the window and the pixmap
  972.  */
  973. void xdis(w,s,n)
  974. register wbp w;
  975. char *s;
  976. int n;
  977.    {
  978.    XPoint pt;
  979.    HBRUSH hb;
  980.    XRectangle rect;
  981.    STDLOCALS(w);
  982.  
  983.    STDFONT;
  984.    rect.left = ws->x; rect.right = ws->x + dc_textwidth(pixdc, s, n);
  985.    rect.top = ws->y - ASCENT(w); rect.bottom = ws->y + DESCENT(w);
  986.  
  987.    /* skip resource allocation if we are offscreen */
  988.    if (!(rect.left > ws->width || rect.right < 0 ||
  989.        rect.top < 0 || rect.bottom > ws->height)) {
  990.  
  991.       hb = CreateBrushIndirect(&(wc->bgbrush));
  992.       if (stdwin) {
  993.          /*
  994.           *  SetBkColor() does not dither consistently with bgbrush;
  995.           *  erase the background beforehand and use transparent drawing
  996.           */
  997.          FillRect(stddc, &rect, hb);
  998.          SetBkMode(stddc, TRANSPARENT);
  999.          SetTextColor(stddc, PALCLR(wc->fg));
  1000.          TextOut(stddc, ws->x, ws->y - ASCENT(w), s, n);
  1001.          }
  1002.       FillRect(pixdc, &rect, hb);
  1003.       DeleteObject(hb);
  1004.       SetBkMode(pixdc, TRANSPARENT);
  1005.       SetTextColor(pixdc, PALCLR(wc->fg));
  1006.       TextOut(pixdc, ws->x, ws->y - ASCENT(w), s, n);
  1007.       }
  1008.    ws->x += dc_textwidth(pixdc, s, n);
  1009.  
  1010.    FREE_STDLOCALS(w);
  1011.    }
  1012. /*
  1013.  * wputc
  1014.  */
  1015. int wputc(int ci, wbp w)
  1016.    {
  1017.    char c = (char)ci;
  1018.    wsp ws = w->window;
  1019.    wcp wc = w->context;
  1020.    int y_plus_descent;
  1021.    HBRUSH hb;
  1022.  
  1023.    switch (c) {
  1024.    case '\n':
  1025.       ws->y += LEADING(w);
  1026.       if (ws->y + DESCENT(w) > ws->height) {
  1027.      RECT r;
  1028.      STDLOCALS(w);
  1029.      ws->y -= LEADING(w);
  1030.      y_plus_descent = ws->y + DESCENT(w);
  1031.      BitBlt(pixdc, 0, 0,
  1032.         ws->width, y_plus_descent,
  1033.         pixdc, 0, LEADING(w), SRCCOPY);
  1034.      r.left = 0;
  1035.      r.top = y_plus_descent - FHEIGHT(w);
  1036.      r.right = ws->width;
  1037.      r.bottom = ws->height;
  1038.          hb = CreateBrushIndirect(&(wc->bgbrush));
  1039.      FillRect(pixdc, &r, hb);
  1040.      DeleteObject(hb);
  1041.      if (stdwin)
  1042.         BitBlt(stddc, 0, 0, ws->width, ws->height,
  1043.            pixdc, 0, 0, SRCCOPY);
  1044.      FREE_STDLOCALS(w);
  1045.      }
  1046.       /* intended fall-through */
  1047.     case '\r':
  1048.       /*
  1049.        * set the new x position
  1050.        */
  1051.       ws->x = wc->dx;
  1052.       break;
  1053.    case '\t':
  1054.       xdis(w, "        ", 8 - (XTOCOL(w,ws->x) & 7));
  1055.       break;
  1056.       /*
  1057.        * Handle backspaces.  This implements cooked mode echo handling.
  1058.        */
  1059.    case '\177':
  1060.    case '\010': {
  1061.       int i = 0, pre_x;
  1062.  
  1063.       /*
  1064.        * Start with the last character queued up.
  1065.        */
  1066.       i--;
  1067.       /*
  1068.        * Trot back to the control-H itself.
  1069.        */
  1070.       while ((i>-EQUEUELEN) && (EVQUESUB(w,i) != c)) {
  1071.      i--;
  1072.      }
  1073.       if (i == -EQUEUELEN) break;
  1074.       /*
  1075.        * Go past the control-H.
  1076.        */
  1077.       i--;
  1078.       /*
  1079.        * Go back through any number of control-H's from prior lifetimes.
  1080.        */
  1081.       while((i > -EQUEUELEN) && !isprint(EVQUESUB(w,i))) {
  1082.      i--;
  1083.      }
  1084.       if (i == -EQUEUELEN) break;
  1085.  
  1086.       /*
  1087.        * OK, here's the character we're actually rubbing out.  Back up.
  1088.        */
  1089.       c = EVQUESUB(w,i);
  1090.       pre_x = ws->x;
  1091.       ws->x -= TEXTWIDTH(w, &c, 1);
  1092.       /*
  1093.        * Physically erase the character from the queue.  This results in
  1094.        * two control-H's present in the queue.
  1095.        */
  1096.       *evquesub(w,i) = '\010';
  1097.       /*
  1098.        * Save the backed-up position, and draw spaces through the erased.
  1099.        */
  1100.       i = ws->x;
  1101.       while(ws->x < pre_x) {
  1102.      xdis(w, " ",1);
  1103.      }
  1104.       ws->x = i;
  1105.       break;
  1106.       }
  1107.     /*
  1108.      * bell (control-G)
  1109.      */
  1110.     case '\007':
  1111.       break;
  1112.    default:
  1113.       xdis(w, &c, 1);
  1114.       }
  1115.    /*
  1116.     * turn the cursor back on
  1117.     */
  1118.    UpdateCursorPos(ws,wc);
  1119.    return 0;
  1120.    }
  1121.  
  1122. /*
  1123.  * wgetq - get event from pending queue
  1124.  */
  1125. int wgetq(wbp w, dptr res)
  1126.    {
  1127.    MSG m;
  1128.    wsp ws;
  1129.    int first = 0, i = 0, j;
  1130.    int hascaret = 0;
  1131.    extern jmp_buf mark_sj;
  1132.    FILE *f;
  1133.  
  1134.    if (!w || !(ws = w->window) || !(ws->iconwin)) {
  1135.       return -1;
  1136.       }
  1137.    while (1) {
  1138.       /*
  1139.        * grab the built up queue
  1140.        */
  1141.       if (!EVQUEEMPTY(ws)) {
  1142.      EVQUEGET(ws, *res);
  1143.      if (ws->hasCaret) {
  1144.             HideCaret(ws->iconwin);
  1145.             DestroyCaret();
  1146.             ws->hasCaret = 0;
  1147.             }
  1148.      return 1;
  1149.      }
  1150.       if (ISCURSORON(w) && ws->hasCaret == 0) {
  1151.      CreateCaret(ws->iconwin, NULL, FWIDTH(w), FHEIGHT(w));
  1152.      SetCaretPos(ws->x, ws->y - ASCENT(w));
  1153.      SetCaretBlinkTime(500);
  1154.          ShowCaret(ws->iconwin);
  1155.      ws->hasCaret = 1;
  1156.          }
  1157.       i++;
  1158.       if (GetMessage(&m, NULL, 0, 0) == 0) longjmp(mark_sj, -1);
  1159.       TranslateMessage(&m);
  1160.       DispatchMessage(&m);
  1161.       }
  1162.    }
  1163.  
  1164. /*
  1165.  * determine the new size of the client
  1166.  */
  1167. int setheight(w, height)
  1168. wbp w;
  1169. int height;
  1170.    {
  1171.    wsp ws = w->window;
  1172.    ws->height = height;
  1173.    return Succeeded;
  1174.    }
  1175.  
  1176. /*
  1177.  * determine new size of client
  1178.  */
  1179. int setwidth(w, width)
  1180. wbp w;
  1181. SHORT width;
  1182.    {
  1183.    wsp ws = w->window;
  1184.    ws->width = width;
  1185.    return Succeeded;
  1186.    }
  1187.  
  1188. int setgeometry(w, geo)
  1189. wbp w;
  1190. char *geo;
  1191.    {
  1192.    wsp ws = w->window;
  1193.    int width = 0, height = 0;
  1194.    int x = 0, y = 0, status;
  1195.    if ((status = parsegeometry(geo, &x, &y, &width, &height)) == 0)
  1196.       return Error;
  1197.    if (status & 1) {
  1198.       ws->width = width;
  1199.       ws->height = height;
  1200.       }
  1201.    if (status & 2) {
  1202.       ws->posx = x;
  1203.       ws->posy = y;
  1204.       }
  1205.    return Succeeded;
  1206.    }
  1207.  
  1208. int setcanvas(w,s)
  1209. wbp w;
  1210. char *s;
  1211.    {
  1212.    int cmd;
  1213.    wsp ws = w->window;
  1214.    HWND stdwin = ws->win;
  1215.  
  1216.    if (!strcmp(s, "iconic")) {
  1217.       cmd = SW_MINIMIZE;
  1218.       CLRTOBEHIDDEN(ws);
  1219.       }
  1220.    else if (!strcmp(s, "normal")) {
  1221.       cmd = SW_RESTORE;
  1222.       stdwin = ws->win = ws->iconwin;
  1223.       CLRTOBEHIDDEN(ws);
  1224.       }
  1225.    else if (!strcmp(s, "maximal")) {
  1226.       cmd = SW_SHOWMAXIMIZED;
  1227.       stdwin = ws->win = ws->iconwin;
  1228.       CLRTOBEHIDDEN(ws);
  1229.       }
  1230.    else if (!strcmp(s, "hidden")) {
  1231.       cmd = SW_HIDE;
  1232.       SETTOBEHIDDEN(ws);
  1233.       }
  1234.    else {
  1235.       return Error;
  1236.       }
  1237.    if (stdwin)
  1238.       ShowWindow(stdwin, cmd);
  1239.  
  1240.    return Succeeded;
  1241.    }
  1242.  
  1243. int seticonicstate(w, val)
  1244. wbp w;
  1245. char *val;
  1246.    {
  1247.    int height;
  1248.    return Failed;
  1249.    }
  1250.  
  1251. int seticonlabel(w, val)
  1252. wbp w;
  1253. char *val;
  1254.    {
  1255.    wsp ws = w->window;
  1256.    if (ws->iconlabel != NULL) free(ws->iconlabel);
  1257.    ws->iconlabel = salloc(val);
  1258.    if (ws->win && IsIconic(ws->win))
  1259.       SetWindowText(ws->win, ws->iconlabel);
  1260.    return Succeeded;
  1261.    }
  1262.  
  1263. int seticonpos(w, val)
  1264. wbp w;
  1265. char *val;
  1266.    {
  1267.    return Failed;
  1268.    }
  1269.  
  1270.  
  1271. int setwindowlabel(w, val)
  1272. wbp w;
  1273. char *val;
  1274.    {
  1275.    wsp ws = w->window;
  1276.    /*
  1277.     * plug in the new string
  1278.     */
  1279.    if (ws->windowlabel != NULL)
  1280.       free(ws->windowlabel);
  1281.    ws->windowlabel = salloc(val);
  1282.  
  1283.    /*
  1284.     * if we have to update, do it
  1285.     */
  1286.    if (ws->win && !IsIconic(ws->win))
  1287.       SetWindowText(ws->win, ws->windowlabel);
  1288.    return Succeeded;
  1289.    }
  1290.  
  1291. int setcursor(w, on)
  1292. wbp w;
  1293. int on;
  1294.    {
  1295.    wsp ws = w->window;
  1296.    if (on) {
  1297.       SETCURSORON(w);
  1298.       }
  1299.    else {
  1300.       CLRCURSORON(w);
  1301.       }
  1302.    return Succeeded;
  1303.    }
  1304.  
  1305. HFONT findfont(char *family, int size, int flags, int ansi)
  1306. {
  1307.    int weight;
  1308.    char slant, spacing;
  1309.  
  1310.    if (size < 0) size = DEFAULTFONTSIZE;
  1311.  
  1312.    if (flags & FONTFLAG_MEDIUM)
  1313.       weight = FW_MEDIUM;
  1314.    else if ((flags & FONTFLAG_DEMI) && (flags & FONTFLAG_BOLD))
  1315.       weight = FW_DEMIBOLD;
  1316.    else if (flags & FONTFLAG_BOLD)
  1317.       weight = FW_BOLD;
  1318.    else if (flags & FONTFLAG_DEMI)
  1319.       weight = FW_SEMIBOLD;
  1320.    else if (flags & FONTFLAG_LIGHT)
  1321.       weight = FW_LIGHT;
  1322.    else
  1323.       weight = FW_DONTCARE;
  1324.  
  1325.    if (flags & FONTFLAG_ITALIC)
  1326.       slant = 1;
  1327.    else
  1328.       slant = 0;
  1329.  
  1330.    if (flags & FONTFLAG_PROPORTIONAL)
  1331.       spacing = VARIABLE_PITCH;
  1332.    else if (flags & FONTFLAG_MONO)
  1333.       spacing = FIXED_PITCH;
  1334.    else spacing = DEFAULT_PITCH;
  1335.  
  1336.    return CreateFont(size, 0, 0, 0, weight, slant, 0, 0,
  1337.         (ansi && (MAXBYTESPERCHAR==1)) ? ANSI_CHARSET:DEFAULT_CHARSET,
  1338.         OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
  1339.         spacing, family);
  1340. }
  1341.  
  1342. HFONT mkfont(char *s)
  1343. {
  1344.    int flags, size;
  1345.    char family[MAXFONTWORD+1];
  1346.    char *stdfam = NULL;
  1347.    HFONT hf = 0;
  1348.  
  1349.    if (parsefont(s, family, &flags, &size)) {
  1350.       /*
  1351.        * This is a legal Icon font spec.
  1352.        * Check first for special "standard" family names.
  1353.        */
  1354.       if (!strcmp(family, "mono") || !strcmp(family, "fixed")) {
  1355.      stdfam = "Lucida Sans";
  1356.      flags |= FONTFLAG_MONO + FONTFLAG_SANS;
  1357.      }
  1358.       else if (!strcmp(family, "typewriter")) {
  1359.      stdfam = "Courier New"; /* was "courier" */
  1360.      flags |= FONTFLAG_MONO + FONTFLAG_SERIF;
  1361.      }
  1362.       else if (!strcmp(family, "sans")) {
  1363.      stdfam = "Arial"; /* was "swiss" */
  1364.      flags |= FONTFLAG_PROPORTIONAL + FONTFLAG_SANS;
  1365.      }
  1366.       else if (!strcmp(family, "serif")) {
  1367.      stdfam = "Times New Roman";
  1368.      flags |= FONTFLAG_PROPORTIONAL + FONTFLAG_SERIF;
  1369.      }
  1370.       else stdfam = NULL;
  1371.  
  1372.       if (stdfam) {
  1373.      /*
  1374.       * Standard name: first try preferred family, then generalize.
  1375.       * ICONFONT can be NULL, in which case Windows chooses.
  1376.       */
  1377.      hf = findfont(stdfam, size, flags, 1);
  1378.      if (hf == NULL)
  1379.         hf = findfont(getenv("ICONFONT"), size, flags, 1);
  1380.      }
  1381.       else {
  1382.      /*
  1383.       * Any other name: must match as specified.
  1384.       */
  1385.      hf = findfont(family, size, flags, 0);
  1386.      }
  1387.       }
  1388.    return hf;
  1389. }
  1390.  
  1391. /*
  1392.  * Set the window's font by name.
  1393.  */
  1394. int setfont(w, s)
  1395. wbp w;
  1396. char **s;
  1397.    {
  1398.    wsp ws = w->window;
  1399.    wcp wc = w->context;
  1400.    HFONT hf, oldfont;
  1401.    TEXTMETRIC    metrics;
  1402.    HDC tmpdc;
  1403.  
  1404.    hf = mkfont(*s);
  1405.    if (hf != NULL) {
  1406.       if (wc->font->font)
  1407.      DeleteObject(wc->font->font);
  1408.       wc->font->font = hf;
  1409.       if (wc->font->name)
  1410.          free(wc->font->name);
  1411.       wc->font->name = salloc(*s);
  1412.  
  1413.       tmpdc = GetDC(ws->iconwin);
  1414.       oldfont = SelectObject(tmpdc, hf);
  1415.       wc->font->charwidth = dc_maxcharwidth(tmpdc);
  1416.       if (GetTextMetrics(tmpdc, &metrics) == 0) {
  1417.          /* gettextmetrics can fail; what should we do about it? */
  1418.          ;
  1419.          }
  1420.       SelectObject(tmpdc, oldfont);
  1421.       ReleaseDC(ws->iconwin, tmpdc);
  1422.       wc->font->ascent = metrics.tmAscent;
  1423.       wc->font->descent = metrics.tmDescent;
  1424. /*    wc->font->charwidth = metrics.tmMaxCharWidth; unreliable due to MS bug */
  1425.       wc->leading = wc->font->height = metrics.tmHeight;
  1426.       return Succeeded;
  1427.       }
  1428.    return Failed;
  1429.    }
  1430.  
  1431. /*
  1432.  * rebind() - bind w's context to that of w2.
  1433.  */
  1434. int rebind(w, w2)
  1435. wbp w, w2;
  1436.    {
  1437.    wsp ws = w->window;
  1438.    /* decrement w->context->refcount?  increment w2->context->refcount? */
  1439.    w->context = w2->context;
  1440.    return Succeeded;
  1441.    }
  1442.  
  1443. void setclip(w)
  1444. wbp w;
  1445.    {
  1446.    wcp wc = w->context;
  1447.    if (wc->cliprgn)
  1448.       DeleteObject(wc->cliprgn);
  1449.    if (wc->clipw >= 0)
  1450.       wc->cliprgn = CreateRectRgn(wc->clipx, wc->clipy,
  1451.                   wc->clipx + wc->clipw,
  1452.                   wc->clipy + wc->cliph);
  1453.    else
  1454.       wc->cliprgn = NULL;
  1455.    }
  1456.  
  1457. void unsetclip(w)
  1458. wbp w;
  1459.    {
  1460.    wcp wc = w->context;
  1461.    if (wc->cliprgn)
  1462.       DeleteObject(wc->cliprgn);
  1463.    wc->cliprgn = NULL;
  1464.    }
  1465.  
  1466.  int lowerWindow(wbp w)
  1467.    {
  1468.    wsp ws = w->window;
  1469.    if (ws->win)
  1470.       SetWindowPos(ws->win, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
  1471.    return Succeeded;
  1472.    }
  1473.  
  1474. int raiseWindow(wbp w)
  1475.    {
  1476.    wsp ws = w->window;
  1477.    if (ws->win)
  1478.       SetWindowPos(ws->win, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
  1479.    return Succeeded;
  1480.    }
  1481.  
  1482. int nativecolor(w, s, r, g, b)
  1483. wbp w;
  1484. char *s;
  1485. long *r, *g, *b;
  1486.    {
  1487.    return 0;                    /* no new colors beyond those of Icon */
  1488.    }
  1489. /*
  1490.  * convert an Icon linear color into an MS Windows color value
  1491.  */
  1492. SysColor mscolor(wbp w, long r, long g, long b)
  1493. {
  1494.    SysColor x;
  1495.    double invgamma = 1.0 / w->context->gamma;
  1496.    long int red, green, blue;
  1497.  
  1498.    red   = 65535L * pow(r / 65535.0, invgamma);
  1499.    green = 65535L * pow(g / 65535.0, invgamma);
  1500.    blue  = 65535L * pow(b / 65535.0, invgamma);
  1501.    return RGB(red >> 8, green >> 8, blue >> 8);
  1502. }
  1503.  
  1504. /*
  1505.  * Set the context's fill style by name.
  1506.  */
  1507. int setfillstyle(w, s)
  1508. wbp w;
  1509. char *s;
  1510.    {
  1511.    wcp wc = w->context;
  1512.  
  1513.    if (!strcmp(s, "solid")) {
  1514.       wc->brush.lbStyle = wc->fillstyle = BS_SOLID;
  1515.       wc->brush.lbColor = PALCLR(wc->fg);
  1516.       }
  1517.    else {
  1518.       if (!strcmp(s, "masked")
  1519.       || !strcmp(s, "stippled") || !strcmp(s, "patterned")) {
  1520.      wc->brush.lbStyle = wc->fillstyle = BS_PATTERN;
  1521.      wc->brush.lbColor = PALCLR(wc->fg);
  1522.      wc->brush.lbHatch = (LONG)wc->pattern;
  1523.          wc->bkmode = TRANSPARENT;
  1524.      }
  1525.       else if (!strcmp(s, "textured")
  1526.       || !strcmp(s, "opaquestippled") || !strcmp(s, "opaquepatterned")) {
  1527.      wc->brush.lbStyle = wc->fillstyle = BS_PATTERN;
  1528.      wc->brush.lbColor = PALCLR(wc->fg);
  1529.      wc->brush.lbHatch = (LONG)wc->pattern;
  1530.          wc->bkmode = OPAQUE;
  1531.      }
  1532.       else {
  1533.      return Error;
  1534.      }
  1535.       }
  1536.    return Succeeded;
  1537.    }
  1538.  
  1539. /*
  1540.  * Set the context's line style by name.
  1541.  */
  1542. int setlinestyle(w, s)
  1543. wbp w;
  1544. char *s;
  1545.    {
  1546.    wcp wc = w->context;
  1547.    SHORT ltype;
  1548.  
  1549.    if ((ltype = si_s2i(siLineTypes, s)) < 0)
  1550.       return Error;
  1551.    wc->pen.lopnStyle = ltype;
  1552.    resetfg(w);
  1553.    if(!strcmp(s, "striped")) wc->bkmode = OPAQUE;
  1554.    else wc->bkmode = TRANSPARENT;
  1555.    return Succeeded;
  1556.    }
  1557.  
  1558. /*
  1559.  * Set the context's line width
  1560.  */
  1561. int setlinewidth(wbp w, LONG linewid)
  1562.    {
  1563.    wcp wc = w->context;
  1564.    wc->pen.lopnWidth.x = wc->pen.lopnWidth.y =
  1565.       wc->bgpen.lopnWidth.x = wc->bgpen.lopnWidth.y = linewid;
  1566.    return Succeeded;
  1567.    }
  1568.  
  1569.  
  1570. /*
  1571.  * Set the foreground to draw in a mutable color
  1572.  */
  1573. int isetfg(wbp w, int i)
  1574.    {
  1575.    char tmp[20];
  1576.    wcp wc = w->context;
  1577.    if (-i > numColors) return Failed;
  1578.    wc->fg = (0x01000000L | -i);
  1579.    sprintf(tmp, "%ld", -i);
  1580.    if (wc->fgname != NULL) free(wc->fgname);
  1581.    wc->fgname = salloc(tmp);
  1582.    wc->pen.lopnColor = wc->fg;
  1583.    wc->brush.lbStyle = BS_SOLID;
  1584.    wc->brush.lbColor = wc->fg;
  1585.    return Succeeded;
  1586.    }
  1587.  
  1588. /*
  1589.  * Set the context's background color by color cell.
  1590.  */
  1591. int isetbg(w, i)
  1592. wbp w;
  1593. int i;
  1594.    {
  1595.    char tmp[20];
  1596.    wcp wc = w->context;
  1597.    if (-i > numColors) return Failed;
  1598.    wc->bg = (0x01000000L | -i);
  1599.    sprintf(tmp, "%ld", -i);
  1600.    if (wc->bgname != NULL) free(wc->bgname);
  1601.    wc->bgname = salloc(tmp);
  1602.    wc->bgpen.lopnColor = wc->bg;
  1603.    wc->bgbrush.lbStyle = BS_SOLID;
  1604.    wc->bgbrush.lbColor = wc->bg;
  1605.    return ISXORREVERSE(w) ? resetfg(w) : Succeeded;
  1606.    }
  1607.  
  1608.  
  1609. int getdepthDC(HDC dc)
  1610. {
  1611.    return GetDeviceCaps(dc, BITSPIXEL) * GetDeviceCaps(dc, PLANES);
  1612. }
  1613.  
  1614. int getdepth(wbp w)
  1615. {
  1616.    int i, j;
  1617.    STDLOCALS(w);
  1618.    i = GetDeviceCaps(pixdc, BITSPIXEL);
  1619.    j = GetDeviceCaps(pixdc, PLANES);
  1620.    FREE_STDLOCALS(w);
  1621.    return i * j;
  1622. }
  1623.  
  1624. int devicecaps(wbp w, int i)
  1625. {
  1626.    int rv;
  1627.    STDLOCALS(w);
  1628.    rv = GetDeviceCaps(pixdc, i);
  1629.    FREE_STDLOCALS(w);
  1630.    return rv;
  1631. }
  1632.  
  1633. /*
  1634.  * Reset the context's foreground color to whatever it is supposed to be.
  1635.  */
  1636. int resetfg(w)
  1637. wbp w;
  1638.    {
  1639.    return setfg(w, w->context->fgname);
  1640.    }
  1641.  
  1642. int alc_rgb(wbp w, SysColor rgb)
  1643. {
  1644.    int i;
  1645.    wsp ws = w->window;
  1646.    HDC hdc;
  1647.    PALETTEENTRY pe;
  1648.    LOGPALETTE lp;
  1649.    if (palette) {
  1650.       for (i=0; i < numColors; i++) {
  1651.          if (rgb == scp[i].c && scp[i].type == SHARED) break;
  1652.      }
  1653.       if (i == numColors) {
  1654.          numColors++;
  1655.      if (ResizePalette(palette, numColors) == 0) {
  1656.         numColors--;
  1657.         return Failed;
  1658.             }
  1659.          scp = realloc(scp, numColors * sizeof(struct wcolor));
  1660.          if (scp == NULL) { numColors--; return Failed; }
  1661.      scp[numColors - 1].c = rgb;
  1662.      scp[numColors - 1].type = SHARED;
  1663.      sprintf(scp[numColors - 1].name, "%d,%d,%d",
  1664.                  RED(rgb), GREEN(rgb), BLUE(rgb));
  1665.          lp.palNumEntries = 1;
  1666.      lp.palVersion = 0x300;
  1667.      lp.palPalEntry[0].peFlags = 0;
  1668.      lp.palPalEntry[0].peRed = RED(rgb);
  1669.      lp.palPalEntry[0].peGreen = GREEN(rgb);
  1670.      lp.palPalEntry[0].peBlue = BLUE(rgb);
  1671.          SetPaletteEntries(palette, numColors - 1, 1, lp.palPalEntry);
  1672.      hdc = GetDC(ws->iconwin);
  1673.      SelectPalette(hdc, palette, FALSE);
  1674.      RealizePalette(hdc);
  1675.      ReleaseDC(ws->iconwin, hdc);
  1676.      }
  1677.       }
  1678.    return Succeeded;
  1679. }
  1680.  
  1681. /*
  1682.  * Set the context's foreground color
  1683.  */
  1684. int setfg(wbp w, char *val)
  1685.    {
  1686.    long r, g, b;
  1687.    wcp wc = w->context;
  1688.    if (parsecolor(w, val, &r, &g, &b) == Succeeded) {
  1689.       wc->fg = mscolor(w, r, g, b);
  1690.       if (alc_rgb(w, wc->fg) == Failed) return Failed;
  1691.       if (!wc->fgname) wc->fgname = salloc(val);
  1692.       else if (strcmp(wc->fgname, val)) {
  1693.          free(wc->fgname);
  1694.          wc->fgname = salloc(val);
  1695.      }
  1696.       wc->brush.lbColor =
  1697.      PALCLR(ISXORREVERSE(w) ? ((wc->fg ^ wc->bg) & 0x00FFFFFF) : wc->fg);
  1698.       wc->pen.lopnColor = wc->brush.lbColor;
  1699.       wc->brush.lbStyle = wc->fillstyle;
  1700.       if (wc->fillstyle == BS_PATTERN)
  1701.      wc->brush.lbHatch = (LONG)wc->pattern;
  1702.       return Succeeded;
  1703.       }
  1704.    return Failed;
  1705.    }
  1706.  
  1707. /*
  1708.  * Set the window context's background color
  1709.  */
  1710. int setbg(wbp w, char *val)
  1711.    {
  1712.    long r, g, b;
  1713.    wcp wc = w->context;
  1714.    if (parsecolor(w, val, &r, &g, &b) == Succeeded) {
  1715.       wc->bg = mscolor(w, r, g, b);
  1716.       if (alc_rgb(w, wc->bg) == Failed) return Failed;
  1717.       if (!wc->bgname) wc->bgname = salloc(val);
  1718.       else if (strcmp(wc->bgname, val)) {
  1719.          free(wc->bgname);
  1720.          wc->bgname = salloc(val);
  1721.      }
  1722.       wc->bgpen.lopnColor = PALCLR(wc->bg);
  1723.       wc->bgbrush.lbStyle = BS_SOLID;
  1724.       wc->bgbrush.lbColor = PALCLR(wc->bg);
  1725.       return ISXORREVERSE(w) ? resetfg(w) : Succeeded;
  1726.       }
  1727.    return Failed;
  1728.    }
  1729.  
  1730. /*
  1731.  * Set the gamma correction factor.
  1732.  */
  1733. int setgamma(w, gamma)
  1734. wbp w;
  1735. double gamma;
  1736.    {
  1737.    wcp wc = w->context;
  1738.    wc->gamma = gamma;
  1739.    setfg(w, wc->fgname);
  1740.    setbg(w, wc->bgname);
  1741.    return Succeeded;
  1742.    }
  1743.  
  1744. /*
  1745.  * setpointer() - define a mouse pointer shape
  1746.  */
  1747. int setpointer(w, val)
  1748. wbp w;
  1749. char *val;
  1750.    {
  1751.    HCURSOR c;
  1752.    char *cval;
  1753.    if (!strcmp(val,"arrow")) cval = IDC_ARROW;
  1754.    else if (!strcmp(val,"cross")) cval = IDC_CROSS;
  1755.    else if (!strcmp(val,"ibeam")) cval = IDC_IBEAM;
  1756.    else if (!strcmp(val,"uparrow")) cval = IDC_UPARROW;
  1757.    else if (!strcmp(val,"wait")) cval = IDC_WAIT;
  1758.    else if (!strcmp(val,"starting")) cval = IDC_APPSTARTING;
  1759.    else if (!strcmp(val,"icon")) cval = IDC_ICON;
  1760.    else if (!strcmp(val,"size")) cval = IDC_SIZE;
  1761.    else if (!strcmp(val,"sizenesw")) cval = IDC_SIZENESW;
  1762.    else if (!strcmp(val,"sizens")) cval = IDC_SIZENS;
  1763.    else if (!strcmp(val,"sizenwse")) cval = IDC_SIZENWSE;
  1764.    else if (!strcmp(val,"sizewe")) cval = IDC_SIZEWE;
  1765.    else if (!strcmp(val,"no")) cval = IDC_NO;
  1766.    else {
  1767.       return Failed;
  1768.       }
  1769.    c = LoadCursor(NULL, cval);
  1770.    if (c == NULL) {
  1771.      return Failed;
  1772.      }
  1773.    w->window->curcursor = c;
  1774.    if (w->window->cursorname) free(w->window->cursorname);
  1775.    w->window->cursorname = salloc(val);
  1776.    if (! w->window->savedcursor)
  1777.       w->window->savedcursor = SetCursor(c);
  1778.    else (void) SetCursor(c);
  1779.    /* should restore savedcursor when pointer moves outside our window */
  1780.    return Succeeded;
  1781.    }
  1782.  
  1783. /*
  1784.  * setdrawop() - set the drawing operation
  1785.  */
  1786. int setdrawop(w, val)
  1787. wbp w;
  1788. char *val;
  1789.    {
  1790.    wcp wc = w->context;
  1791.    if (!strcmp(val,"reverse")) {
  1792.       if (!ISXORREVERSE(w)) {
  1793.      SETXORREVERSE(w);
  1794.          wc->drawop = R2_XORPEN;
  1795.          resetfg(w);
  1796.      }
  1797.       }
  1798.    else {
  1799.       if (ISXORREVERSE(w)) {
  1800.      CLRXORREVERSE(w);
  1801.          resetfg(w);
  1802.      }
  1803.       wc->drawop = si_s2i(drawops,val);
  1804.       if (wc->drawop == -1) { wc->drawop = R2_COPYPEN; return Error; }
  1805.       }
  1806.    return Succeeded;
  1807.    }
  1808.  
  1809. setdisplay(wbp w, char *val)
  1810.    {
  1811.    if (strcmp(val, "MS Windows"))
  1812.       return Failed;
  1813.    return Succeeded;
  1814.    }
  1815.  
  1816. setimage(wbp w, char *val)
  1817.    {
  1818.    wsp ws = w->window;
  1819.    int status;
  1820.    ws->initialPix = loadimage(w, val, &(ws->width), &(ws->height),
  1821.               0, &status);
  1822.    if (ws->initialPix == (HBITMAP) NULL) return Failed;
  1823.    return Succeeded;
  1824.    }
  1825.  
  1826. setleading(w, i)
  1827. wbp w;
  1828. int i;
  1829.    {
  1830.    wcp wc = w->context;
  1831.    wc->leading = i;
  1832.    }
  1833.  
  1834. void toggle_fgbg(w)
  1835. wbp w;
  1836.    {
  1837.    SysColor tmp;
  1838.    LOGPEN tpen;
  1839.    LOGBRUSH tbrush;
  1840.    wcp wc = w->context;
  1841.    tmp = wc->fg;
  1842.    wc->fg = wc->bg;
  1843.    wc->bg = tmp;
  1844.    tpen = wc->pen;
  1845.    wc->pen = wc->bgpen;
  1846.    wc->bgpen = tpen;
  1847.    tbrush = wc->brush;
  1848.    wc->brush = wc->bgbrush;
  1849.    wc->bgbrush = tbrush;
  1850.    }
  1851.  
  1852. int getvisual(w, answer)
  1853. wbp w;
  1854. char *answer;
  1855.    {
  1856.    return Failed;
  1857.    }
  1858.  
  1859. /*
  1860.  * getpos() - update the window state's notion of its current position
  1861.  */
  1862. int getpos(w)
  1863. wbp w;
  1864.    {
  1865.    return Succeeded;
  1866.    }
  1867.  
  1868. void getfg(w, answer)
  1869. wbp w;
  1870. char *answer;
  1871.    {
  1872.    strcpy(answer, w->context->fgname);
  1873.    }
  1874.  
  1875. void getbg(w, answer)
  1876. wbp w;
  1877. char *answer;
  1878.    {
  1879.    strcpy(answer, w->context->bgname);
  1880.    }
  1881.  
  1882. void getlinestyle(w, answer)
  1883. wbp w;
  1884. char *answer;
  1885.    {
  1886.    wcp wc = w->context;
  1887.    char *ptr = si_i2s(siLineTypes, wc->pen.lopnStyle);
  1888.    if (ptr != NULL) {
  1889.       strcpy(answer, ptr);
  1890.       }
  1891.    else strcpy(answer, "unknown");
  1892.    }
  1893.  
  1894. void getfntnam(w, answer)
  1895. wbp w;
  1896. char *answer;
  1897.    {
  1898.    strcpy(answer, w->context->font->name);
  1899.    }
  1900.  
  1901. void getpointername(w, answer)
  1902. wbp w;
  1903. char *answer;
  1904.    {
  1905.    char *s;
  1906.    wsp ws = w->window;
  1907.    strcpy(answer, w->window->cursorname);
  1908.    }
  1909.  
  1910. void getdisplay(wbp w, char *answer)
  1911.    {
  1912.    strcpy(answer, "MS Windows");
  1913.    }
  1914.  
  1915. void getdrawop(w, answer)
  1916. wbp w;
  1917. char *answer;
  1918.    {
  1919.    char *s;
  1920.    if (ISXORREVERSE(w)) s = "reverse";
  1921.    else s = si_i2s(drawops, w->context->drawop);
  1922.    if (s) sprintf(answer, "%s", s);
  1923.    else strcpy(answer, "unknown");
  1924.    }
  1925.  
  1926. void geticonic(w, answer)
  1927. wbp w;
  1928. char *answer;
  1929.    {
  1930.    getcanvas(w, answer);
  1931.    }
  1932.  
  1933. void getcanvas(w, answer)
  1934. wbp w;
  1935. char *answer;
  1936.    {
  1937.    wsp ws = w->window;
  1938.    if (ws->iconwin) {
  1939.       if (!IsWindowVisible(ws->iconwin)) sprintf(answer, "hidden");
  1940.       else if (IsIconic(ws->iconwin)) sprintf(answer, "iconic");
  1941.       else if (IsZoomed(ws->iconwin)) sprintf(answer, "maximal");
  1942.       else sprintf(answer,"normal");
  1943.       }
  1944.    else sprintf(answer,"hidden");
  1945.    }
  1946.  
  1947. int geticonpos(w, val)
  1948. wbp w;
  1949. char *val;
  1950.    {
  1951.    return Failed;
  1952.    }
  1953.  
  1954. /*
  1955.  * erase an area
  1956.  */
  1957. void eraseArea(w,x,y,width,height)
  1958. wbp w;
  1959. int x, y, width, height;
  1960.    {
  1961.    HBRUSH hb, oldbrush, oldbrush2;
  1962.    XRectangle rect;
  1963.    STDLOCALS(w);
  1964.    hb = CreateBrushIndirect(&(wc->bgbrush));
  1965.    if (stdwin) oldbrush = SelectObject(stddc, hb);
  1966.    oldbrush2 = SelectObject(pixdc, hb);
  1967.    rect.left = x; rect.right = x + width;
  1968.    rect.top = y; rect.bottom = y + height;
  1969.  
  1970.    if (stdwin) FillRect(stddc, &rect, hb);
  1971.    FillRect(pixdc, &rect, hb);
  1972.    if (stdwin) SelectObject(stddc, oldbrush);
  1973.    SelectObject(pixdc, oldbrush2);
  1974.    DeleteObject(hb);
  1975.    FREE_STDLOCALS(w);
  1976.    }
  1977.  
  1978. /*
  1979.  * copy an area
  1980.  */
  1981. int copyArea(w,w2,x,y,width,height,x2,y2)
  1982. wbp w, w2;
  1983. int x, y, width, height, x2, y2;
  1984.    {
  1985.    int lpad, rpad, tpad, bpad;
  1986.    RECT r;
  1987.    HDC srcdc, srcpixdc;
  1988.    HBRUSH hb;
  1989.    wsp ws1 = w->window;
  1990.    HBITMAP oldpix;
  1991.    STDLOCALS(w2);
  1992.    /*
  1993.     * setup device contexts for area copy
  1994.     */
  1995.    SetROP2(pixdc, R2_COPYPEN);
  1996.    hb = CreateBrushIndirect(&(wc->bgbrush));
  1997.    if (stdwin)
  1998.       SetROP2(stddc, R2_COPYPEN);
  1999.    if (w2->window == w->window) {
  2000.       srcdc = pixdc;
  2001.       srcpixdc = pixdc;
  2002.       }
  2003.    else {
  2004.       srcdc = GetDC(w->window->iconwin);
  2005.       srcpixdc = CreateCompatibleDC(srcdc);
  2006.       SetROP2(srcpixdc, R2_COPYPEN);
  2007.       }
  2008.    oldpix = SelectObject(srcpixdc, w->window->pix);
  2009.  
  2010.    /*
  2011.     * copy area, write unavailable areas with bg color
  2012.     */
  2013.    if (x + width < 0 || y + height < 0 || x >= ws1->pixwidth || y >= ws1->pixheight) {
  2014.       /* source is entirely offscreen, just fill with background */
  2015.       r.left = x2; r.top = y2;
  2016.       r.right = x2 + width; r.bottom = y2 + height;
  2017.       if (stdwin)
  2018.          FillRect(stddc, &r, hb);
  2019.       FillRect(pixdc, &r, hb);
  2020.       }
  2021.    else {
  2022.      /*
  2023.       * Check for source partially offscreen, but copy first and
  2024.       * fill later in case the source and destination overlap.
  2025.       */
  2026.      lpad = rpad = tpad = bpad = 0;
  2027.          if (x < 0) {            /* source extends past left edge */
  2028.         lpad = -x;
  2029.             width -= lpad;
  2030.             x2 += lpad;
  2031.             x = 0;
  2032.             }
  2033.          if (x + width > ws1->pixwidth) {  /* source extends past right edge */
  2034.             rpad = x + width - ws1->pixwidth;
  2035.             width -= rpad;
  2036.             }
  2037.          if (y < 0) {            /* source extends above top edge */
  2038.         tpad = -y;
  2039.             height -= tpad;
  2040.             y2 += tpad;
  2041.             y = 0;
  2042.             }
  2043.          if (y + height > ws1->pixheight) {  /* source extends below bottom */
  2044.             bpad = y + height - ws1->pixheight;
  2045.             height -= bpad;
  2046.             }
  2047.       if (stdwin)
  2048.          BitBlt(stddc, x2, y2, width, height, srcpixdc, x, y, SRCCOPY);
  2049.       BitBlt(pixdc, x2, y2, width, height, srcpixdc, x, y, SRCCOPY);
  2050.  
  2051.      if (lpad > 0) {
  2052.             r.left = x2-lpad;
  2053.         r.top = y2-tpad;
  2054.         r.right = r.left + lpad;
  2055.         r.bottom = r.top + tpad+height+bpad;
  2056.             if (stdwin)
  2057.                FillRect(stddc, &r, hb);
  2058.             FillRect(pixdc, &r, hb);
  2059.             }
  2060.      if (rpad > 0) {
  2061.             r.left = x2+width;
  2062.         r.top = y2-tpad;
  2063.         r.right = r.left + rpad;
  2064.         r.bottom = r.top + tpad+height+bpad;
  2065.             if (stdwin)
  2066.                FillRect(stddc, &r, hb);
  2067.             FillRect(pixdc, &r, hb);
  2068.         }
  2069.      if (tpad > 0) {
  2070.         r.left = x2;
  2071.         r.top = y2-tpad;
  2072.         r.right = r.left + width;
  2073.         r.bottom = r.top + tpad;
  2074.             if (stdwin)
  2075.                FillRect(stddc, &r, hb);
  2076.             FillRect(pixdc, &r, hb);
  2077.         }
  2078.      if (bpad > 0) {
  2079.         r.left = x2;
  2080.         r.top = y2+height;
  2081.         r.right = r.left + width;
  2082.         r.bottom = r.top + bpad;
  2083.             if (stdwin)
  2084.                FillRect(stddc, &r, hb);
  2085.             FillRect(pixdc, &r, hb);
  2086.         }
  2087.       }
  2088.  
  2089.    /*
  2090.     * free resources
  2091.     */
  2092.    SelectObject(srcpixdc, oldpix);
  2093.    if (w2->window != w->window) {
  2094.       ReleaseDC(w->window->iconwin, srcdc);
  2095.       DeleteDC(srcpixdc);
  2096.       }
  2097.    DeleteObject(hb);
  2098.    FREE_STDLOCALS(w2);
  2099.    return Succeeded;
  2100.    }
  2101.  
  2102. int getdefault(w, prog, opt, answer)
  2103. wbp w;
  2104. char *prog, *opt, *answer;
  2105.    {
  2106.    return Failed;
  2107.    }
  2108.  
  2109. /*
  2110.  * Draw a bilevel image.
  2111.  */
  2112. int blimage(w, x, y, width, height, ch, s, len)
  2113. wbp w;
  2114. int x, y, width, height, ch;
  2115. unsigned char *s;
  2116. word len;
  2117.    {
  2118.    unsigned int m, msk1, c, ix, iy;
  2119.    long fg, bg;
  2120.    SysColor palfg, palbg;
  2121.    STDLOCALS(w);
  2122.    palfg = PALCLR(wc->fg);
  2123.    palbg = PALCLR(wc->bg);
  2124.    /*
  2125.     * Read the image string and set the pixel values.  Note that
  2126.     * the hex digits in sequence fill the rows *right to left*.
  2127.     */
  2128.    m = width % 4;
  2129.    if (m == 0)
  2130.       msk1 = 8;
  2131.    else
  2132.       msk1 = 1 << (m - 1);              /* mask for first byte of row */
  2133.  
  2134.    fg = wc->fg;
  2135.    bg = wc->bg;
  2136.    ix = width;
  2137.    iy = 0;
  2138.    m = msk1;
  2139.    while (len--) {
  2140.       if (isxdigit(c = *s++)) {         /* if hexadecimal character */
  2141.      if (!isdigit(c))               /* fix bottom 4 bits if necessary */
  2142.         c += 9;
  2143.      while (m > 0) {                /* set (usually) 4 pixel values */
  2144.         --ix;
  2145.         if (c & m) {
  2146.            SetPixel(pixdc, ix, iy, palfg);
  2147.            }
  2148.         else if (ch != TCH1) {      /* if zeroes aren't transparent */
  2149.            SetPixel(pixdc, ix, iy, palbg);
  2150.            }
  2151.         m >>= 1;
  2152.         }
  2153.      if (ix == 0) {                 /* if end of row */
  2154.         ix = width;
  2155.         iy++;
  2156.         m = msk1;
  2157.         }
  2158.      else
  2159.         m = 8;
  2160.      }
  2161.       }
  2162.    if (ix > 0)                          /* pad final row if incomplete */
  2163.       while (ix < width)
  2164.      SetPixel(pixdc, ix++, iy, palbg);
  2165.  
  2166.    /*
  2167.     * Put it on the screen.
  2168.     */
  2169.    if (ws->win)
  2170.       BitBlt(stddc, x, y, width, height, pixdc, x, y, SRCCOPY);
  2171.    FREE_STDLOCALS(w);
  2172.    return Succeeded;
  2173.    }
  2174.  
  2175. /*
  2176.  * Draw a character-per-pixel image.
  2177.  */
  2178. int strimage(w, x, y, width, height, e, s, len, on_icon)
  2179. wbp w;
  2180. int x, y, width, height;
  2181. struct palentry *e;
  2182. unsigned char *s;
  2183. word len;
  2184. int on_icon;
  2185.    {
  2186.    HDC tempdc;
  2187.    HBITMAP temppix;
  2188.    register int c;
  2189.    register unsigned int ix;
  2190.    int v, anytransparent=0;
  2191.    unsigned int iy, tmpw;
  2192.    SysColor clrlist[256], xc, palbg;
  2193.    char tmp[24];
  2194.    BITMAPINFO *bmi;
  2195.    BITMAPINFOHEADER *bmih = &(bmi->bmiHeader);
  2196.    HBITMAP oldpix = 0;
  2197.    STDLOCALS(w);
  2198.  
  2199.    bmi = malloc(sizeof(BITMAPINFO) + 256 * sizeof(SysColor));
  2200.    if (bmi == NULL) {
  2201.       FREE_STDLOCALS(w);
  2202.       return -1;
  2203.       }
  2204.  
  2205.    bmih = &(bmi->bmiHeader);
  2206.    palbg = PALCLR(wc->bg);
  2207.    if (on_icon) {
  2208.       free(bmi);
  2209.       FREE_STDLOCALS(w);
  2210.       return -1;
  2211.       }
  2212.  
  2213.    bmih->biClrImportant = 0;
  2214.    /*
  2215.     * Build arrays of colors in SysColor and RGBQUAD format for use by
  2216.     * either SetPixel or DIB.  Decide which to use based on whether
  2217.     * there are any transparent pixels
  2218.     */
  2219.    for (c = 0; c < 256; c++) {
  2220.       if (e[c].transpt) anytransparent++;
  2221.       if (e[c].used && e[c].valid) {
  2222.          bmih->biClrImportant++;
  2223.      clrlist[c] = mscolor(w, e[c].clr.red, e[c].clr.green, e[c].clr.blue);
  2224.      bmi->bmiColors[c].rgbBlue = BLUE(clrlist[c]);
  2225.      bmi->bmiColors[c].rgbRed = RED(clrlist[c]);
  2226.      bmi->bmiColors[c].rgbGreen = GREEN(clrlist[c]);
  2227.          if (alc_rgb(w, clrlist[c]) == Failed) {
  2228.             free(bmi);
  2229.             FREE_STDLOCALS(w);
  2230.             return -1;
  2231.             }
  2232.      clrlist[c] = PALCLR(clrlist[c]);
  2233.      }
  2234.       else {
  2235.      bmi->bmiColors[c].rgbBlue = BLUE(wc->bg);
  2236.      bmi->bmiColors[c].rgbRed = RED(wc->bg);
  2237.      bmi->bmiColors[c].rgbGreen = GREEN(wc->bg);
  2238.          }
  2239.       }
  2240.  
  2241.    /*
  2242.     * if transparent characters are not present, blast out a DIB.
  2243.     */
  2244.    if (anytransparent == 0) {
  2245.       char *buf = malloc(height * (width+4)), *buf2;
  2246.       buf2 = buf;
  2247.       bmih->biSize = sizeof(BITMAPINFOHEADER);
  2248.       bmih->biWidth = width;
  2249.       bmih->biHeight = -height;
  2250.       bmih->biPlanes = 1;
  2251.       bmih->biBitCount = 8;
  2252.       bmih->biCompression = BI_RGB;
  2253.       bmih->biSizeImage = 0;
  2254.       bmih->biXPelsPerMeter = 0;
  2255.       bmih->biYPelsPerMeter = 0;
  2256.       bmih->biClrUsed = 256;
  2257.  
  2258.       ix = 0;
  2259.       while (len--) {
  2260.          *buf++ = *s++;
  2261.          if (++ix >= width) {
  2262.             while(ix % 4) {
  2263.                buf++;
  2264.                ix++;
  2265.                }
  2266.             ix = 0;
  2267.             }
  2268.          }
  2269.       temppix=CreateDIBitmap(pixdc, bmih, CBM_INIT, buf2, bmi, DIB_RGB_COLORS);
  2270.       free(buf2);
  2271.       tempdc = CreateCompatibleDC(stddc);
  2272.       oldpix = SelectObject(tempdc, temppix);
  2273.       BitBlt(pixdc, x, y, width, height, tempdc, 0, 0, SRCCOPY);
  2274.       SelectObject(tempdc, oldpix);
  2275.       DeleteDC(tempdc);
  2276.       DeleteObject(temppix);
  2277.       }
  2278.    else {
  2279.       /*
  2280.        * The image contains some transparent pixels.
  2281.        * Read the image string and set the pixel values.
  2282.        * Note that SetPixelV() fails under Win32s; so we don't use it.
  2283.        */
  2284.       ix = x;
  2285.       iy = y;
  2286.       tmpw = x + width;
  2287.       while (len--) {
  2288.          c = *s++;
  2289.          v = e[c].valid;
  2290.          if (v) {                         /* put char if valid */
  2291.         xc = SetPixel(pixdc, ix, iy, clrlist[c]);
  2292.         }
  2293.          if (v || e[c].transpt) {        /* advance if valid or transparent */
  2294.         if (++ix >= tmpw) {
  2295.            ix = x;                             /* reset for new row */
  2296.            iy++;
  2297.            }
  2298.         }
  2299.          }
  2300.       if (ix > 0)                          /* pad final row if incomplete */
  2301.          while (ix < width)
  2302.         SetPixel(pixdc, x+ix++, y+iy, palbg);
  2303.       }
  2304.  
  2305.    free(bmi);
  2306.    /*
  2307.     * Copy it from the pixmap onto the screen.
  2308.     */
  2309.    if (on_icon) {
  2310.       FREE_STDLOCALS(w);
  2311.       return -1;
  2312.       }
  2313.    else {
  2314.       if (ws->win)
  2315.      BitBlt(stddc, x, y, width, height, pixdc, x, y, SRCCOPY);
  2316.       }
  2317.    FREE_STDLOCALS(w);
  2318.    return 0;
  2319.    }
  2320.  
  2321. /*
  2322.  * imqsearch(key,base,nel) - binary search hardwired for images
  2323.  *
  2324.  *  A binary search routine with arguments similar to qsort(3).
  2325.  *  Returns a pointer to the item matching "key", or NULL if none.
  2326.  *  This is called a LOT, so it is hardwired for speed.
  2327.  *  Based on Bentley, CACM 28,7 (July, 1985), p. 676.
  2328.  */
  2329.  
  2330. SysColor * imqsearch (SysColor key, SysColor *base, int nel)
  2331. {
  2332.    int l, u, m;
  2333.    SysColor * a;
  2334.  
  2335.    l = 0;
  2336.    u = nel - 1;
  2337.    while (l <= u) {
  2338.       m = (l + u) / 2;
  2339.       a = base + m;
  2340.       if (*a < key)
  2341.          l = m + 1;
  2342.       else if (*a > key)
  2343.          u = m - 1;
  2344.       else
  2345.          return a;
  2346.       }
  2347.    while (a>base && key < *a) a--;
  2348.    while (a<base+nel && key > *a) a++;
  2349.    return a;
  2350. }
  2351.  
  2352. /*
  2353.  * getimstr -- get an image as a string.
  2354.  *
  2355.  * Stores the specified subimage in data, one pixel per byte, and sets
  2356.  * entries in paltbl corresponding to the pixel values that were used.
  2357.  */
  2358. int getimstr(w, xx, yy, width, height, paltbl, data)
  2359. wbp w;
  2360. int xx, yy, width, height;
  2361. struct palentry paltbl[DMAXCOLORS];
  2362. unsigned char *data;
  2363.    {
  2364.    SysColor px, lastpx, *clist, *lp;
  2365.    int i, ncolors, x, y, wd = xx + width, ht = yy + height, nclist;
  2366.    STDLOCALS(w);
  2367.  
  2368.    clist = malloc(DMAXCOLORS * sizeof (SysColor));
  2369.    nclist = DMAXCOLORS;
  2370.    /*
  2371.     * Make a sorted list of the pixel values of the colors that are in
  2372.     * use.  Search this list for every pixel and store the resulting
  2373.     * list index as the color index.
  2374.     */
  2375.    ncolors = 1;
  2376.    clist[0] = lastpx = GetPixel(pixdc, xx, yy);
  2377.    for (y = yy; y < ht; y++) {
  2378. #if 0
  2379.       /* want to do pollevent here, but can't inside a STDLOCALS declaration */
  2380.       if (y & 1) { /* how often to process window events? */
  2381.      pollevent();
  2382.      }
  2383. #endif
  2384.       for (x = xx; x < wd; x++) {
  2385.      px = GetPixel(pixdc, x, y);
  2386.      if (px != lastpx) {
  2387.         lastpx = px;
  2388.         lp = imqsearch(px, clist, ncolors);
  2389.         if (*lp != px) {
  2390.            i = ncolors++;
  2391.                if (ncolors >= nclist) {
  2392.          nclist = nclist * 1.5;
  2393.          clist = realloc(clist, nclist * sizeof (SysColor));
  2394.          }
  2395.            while (clist + i != lp) {
  2396.           clist[i] = clist[i-1];
  2397.           i--;
  2398.           }
  2399.            clist[i] = px;
  2400.            }
  2401.         }
  2402.      }
  2403.       }
  2404.  
  2405.    /*
  2406.     * if ncolors is greater than DMAXCOLORS, then fail rather than
  2407.     * overwriting the paltbl.
  2408.     */
  2409.    if (ncolors > DMAXCOLORS) {
  2410.       free(clist);
  2411.       return 0;
  2412.       }
  2413.  
  2414.    lastpx = GetPixel(pixdc, xx, yy) + 1;
  2415.    for (y = yy; y < height; y++) {
  2416. #if 0
  2417.       /* want to do pollevent here, but can't inside a STDLOCALS declaration */
  2418.       if (y & 1 == 0) {
  2419.      pollevent();
  2420.      }
  2421. #endif
  2422.       for (x = xx; x < width; x++) {
  2423.      px = GetPixel(pixdc, x, y);
  2424.      if (px != lastpx) {
  2425.         lastpx = px;
  2426.         lp = imqsearch(px, clist, ncolors);
  2427.         if (*lp == px)
  2428.            i = lp - clist;
  2429.         else {
  2430.            FREE_STDLOCALS(w);
  2431.            free(clist);
  2432.            return 0;
  2433.            }
  2434.         }
  2435.      *data++ = i;
  2436.      if (!paltbl[i].used) {
  2437.         paltbl[i].used = 1;
  2438.         paltbl[i].clr.red = RED(px) * 257;
  2439.         paltbl[i].clr.green = GREEN(px) * 257;
  2440.         paltbl[i].clr.blue = BLUE(px) * 257;
  2441.         paltbl[i].valid = 1;
  2442.         }
  2443.      }
  2444.       }
  2445.    free(clist);
  2446.    FREE_STDLOCALS(w);
  2447.    return 1;
  2448.    }
  2449.  
  2450. int readimage(w, filename, x, y, status)
  2451. wbp w;
  2452. char *filename;
  2453. int x, y, *status;
  2454.    {
  2455.    HBITMAP p, oldpix;
  2456.    unsigned int width, height;
  2457.    HDC srcdc, srcpixdc;
  2458.  
  2459.    if (!x && !y)
  2460.       p = loadimage(w, filename, &width, &height, 1, status);
  2461.    else
  2462.       p = loadimage(w, filename, &width, &height, 0, status);
  2463.  
  2464.    if (p == (HBITMAP) NULL) {
  2465.      return Failed;
  2466.      }
  2467.  
  2468.    {
  2469.    STDLOCALS(w);
  2470.  
  2471.    srcdc = GetDC(ws->iconwin);
  2472.    srcpixdc = CreateCompatibleDC(srcdc);
  2473.    oldpix = SelectObject(srcpixdc, p);
  2474.    BitBlt(pixdc, x, y, width, height, srcpixdc, 0, 0, SRCCOPY);
  2475.    if (stdwin)
  2476.       BitBlt(stddc, x, y, width, height, srcpixdc, 0, 0, SRCCOPY);
  2477.    SelectObject(srcpixdc, oldpix);
  2478.    ReleaseDC(ws->iconwin, srcdc);
  2479.    DeleteDC(srcpixdc);
  2480.  
  2481.    /*
  2482.     * Make sure previous ops on p are complete, then free it.
  2483.     */
  2484.    DeleteObject(p);
  2485.    FREE_STDLOCALS(w);
  2486.    return Succeeded;
  2487.    }
  2488.    }
  2489.  
  2490.  
  2491.  
  2492. /*
  2493.  * Initialize client for producing pixels from a window, or in this case,
  2494.  * only create a device context once, not once per getpixel.
  2495.  */
  2496. int getpixel_init(w, imem)
  2497. wbp w;
  2498. struct imgmem *imem;
  2499.    {
  2500.    COLORREF *p;
  2501.    wsp ws = w->window;
  2502.    int i, j, x2, y2;
  2503.    HDC stddc = GetDC(ws->iconwin), pixdc = CreateCompatibleDC(stddc);
  2504.    HBITMAP oldpix;
  2505.  
  2506.    if (palette) SelectPalette(pixdc, palette, FALSE);
  2507.    oldpix = SelectObject(pixdc, ws->pix);
  2508.  
  2509.    /* this looks like a bug for Win16 for images > 100x100 or so... */
  2510.    imem->crp = malloc( imem->width * imem->height * sizeof(COLORREF));
  2511.    if (imem->crp == NULL) return Failed;
  2512.    p = imem->crp;
  2513.    x2 = imem->x + imem->width;
  2514.    y2 = imem->y + imem->height;
  2515.    for(i = imem->y; i < y2; i++)
  2516.       for(j = imem->x; j < x2; j++) {
  2517.          if ((*p++ = GetPixel(pixdc, j, i)) == (COLORREF)-1L) {
  2518.         free(imem->crp);
  2519.             SelectObject(pixdc, oldpix);
  2520.             FREE_STDLOCALS(w);
  2521.             return Failed;
  2522.             }
  2523.          }
  2524.    SelectObject(pixdc, oldpix);
  2525.    FREE_STDLOCALS(w);
  2526.    return Succeeded;
  2527.    }
  2528.  
  2529. int getpixel_term(w, imem)
  2530. wbp w;
  2531. struct imgmem *imem;
  2532. {
  2533.    free(imem->crp);
  2534.    return Succeeded;
  2535. }
  2536.  
  2537. /*
  2538.  * Return pixel (x,y) from a window
  2539.  */
  2540. int getpixel(wbp w, int x, int y, long *rv, char *s, struct imgmem *imem)
  2541.    {
  2542.    COLORREF cr = imem->crp[(y-imem->y) * imem->width + (x-imem->x)];
  2543.    *rv = 1;
  2544.    sprintf(s, "%ld,%ld,%ld",
  2545.        (long)RED(cr)*257L, (long)GREEN(cr)*257L, (long)BLUE(cr)*257L);
  2546.    return Succeeded;
  2547.    }
  2548.  
  2549. int query_pointer(w, pp)
  2550. wbp w;
  2551. XPoint *pp;
  2552.    {
  2553.    wsp ws = w->window;
  2554.    RECT r;
  2555.    if (ws->win) {
  2556.       GetCursorPos(pp);
  2557.       GetWindowRect(ws->win, &r);
  2558.       pp->x -= r.left;
  2559.       pp->y -= r.top;
  2560.       return Succeeded;
  2561.       }
  2562.    return Failed;
  2563.    }
  2564.  
  2565. int query_rootpointer(pp)
  2566. XPoint *pp;
  2567.    {
  2568.    GetCursorPos(pp);
  2569.    return Succeeded;
  2570.    }
  2571.  
  2572. int seticonimage(w, dp)
  2573. wbp w;
  2574. dptr dp;
  2575.    {
  2576.    wsp ws = w->window;
  2577.    return Succeeded;
  2578.    }
  2579.  
  2580. /*
  2581.  * dumpimage -- write an image to a disk file.  Return 0 on failure.
  2582.  */
  2583. int dumpimage(wbp w, char *filename, unsigned int x, unsigned int y,
  2584.           unsigned int width, unsigned int height)
  2585.    {
  2586.    int result = 0;
  2587.    HDIB dib;
  2588.    HDC  destdc;
  2589.    HBITMAP dumppix, oldpix;
  2590.    STDLOCALS(w);
  2591.  
  2592.    if (strcmp(".bmp", filename + strlen(filename) - 4) &&
  2593.        strcmp(".BMP", filename + strlen(filename) - 4)) {
  2594.       FREE_STDLOCALS(w);
  2595.       return NoCvt;
  2596.       }
  2597.  
  2598.    /*
  2599.     * extract the desired rectangle from the source bitmap
  2600.     */
  2601.    if (x || y || width != ws->pixwidth || height != ws->pixheight) {
  2602.       dumppix  = CreateCompatibleBitmap(stddc, width, height);
  2603.       destdc   = CreateCompatibleDC(stddc);
  2604.       oldpix = SelectObject(destdc, dumppix);
  2605.       BitBlt(destdc, 0, 0, width, height, pixdc, x, y, SRCCOPY);
  2606.       }
  2607.    else dumppix = ws->pix;
  2608.    dib = BitmapToDIB(dumppix, palette);
  2609.    if (dumppix != ws->pix) {
  2610.       SelectObject(destdc, oldpix);
  2611.       DeleteDC(destdc);
  2612.       DeleteObject(dumppix);
  2613.       }
  2614.  
  2615.    if (dib == NULL) {
  2616.       result = Failed;
  2617.       }
  2618.    else {
  2619.       if (result = SaveDIB(dib, filename)) { /* != 0 implies error */
  2620.      result = Failed;
  2621.      }
  2622.       else {
  2623.          result = Succeeded;
  2624.          }
  2625.       DestroyDIB(dib);
  2626.       }
  2627.  
  2628.    FREE_STDLOCALS(w);
  2629.    return result;
  2630.    }
  2631.  
  2632.  
  2633. /*
  2634.  * loadimage
  2635.  */
  2636. HBITMAP loadimage(wbp w, char *filename, unsigned int *width,
  2637.           unsigned int *height, int atorigin, int *status)
  2638.    {
  2639.    HDC hdc;
  2640.    HDIB dib;
  2641.    HBITMAP bmap;
  2642.    HPALETTE p2;
  2643.    PALETTEENTRY pe;
  2644.    LPBITMAPINFO lpbmi;
  2645.    int j;
  2646.    int ii,jj, kk;
  2647.    int xx[256];
  2648.    unsigned char * pd;
  2649.    char *j2;
  2650.  
  2651.    dib = LoadDIB(filename);
  2652.    if (dib != NULL) {
  2653.       LPSTR pdib;
  2654.       p2 = CreateDIBPalette(dib);
  2655.       j2 = GlobalLock(dib);
  2656.       j = DIBNumColors(j2);
  2657.       jj = DIBWidth(j2);
  2658.       kk = DIBHeight(j2);
  2659.       GlobalUnlock(dib);
  2660.  
  2661.       if (!palette) {
  2662.      LOGPALETTE logpal[4]; /* (1, + space for an extra palette entry) */
  2663.          hdc = GetDC(w->window->iconwin);
  2664.          if ((GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) && (numColors ==0)){
  2665.         /* This window is on a device that supports palettes */
  2666.         numColors = 2;
  2667.         logpal[0].palNumEntries = 2;
  2668.         logpal[0].palVersion = 0x300;
  2669.         logpal[0].palPalEntry[0].peFlags = 0;
  2670.         logpal[0].palPalEntry[0].peRed = 0;
  2671.         logpal[0].palPalEntry[0].peGreen = 0;
  2672.         logpal[0].palPalEntry[0].peBlue = 0;
  2673.         logpal[0].palPalEntry[1].peFlags = 0;
  2674.         logpal[0].palPalEntry[1].peRed = 255;
  2675.         logpal[0].palPalEntry[1].peGreen = 255;
  2676.         logpal[0].palPalEntry[1].peBlue = 255;
  2677.         palette = CreatePalette(logpal);
  2678.         if (!palette) {
  2679.            return NULL;
  2680.            }
  2681.         if ((scp = malloc(2 * sizeof (struct wcolor))) == NULL)
  2682.            return NULL;
  2683.         scp[0].c = RGB(0,0,0);
  2684.         scp[0].type = SHARED;
  2685.         strcpy(scp[0].name, "black");
  2686.         scp[1].c = RGB(255,255,255);
  2687.         scp[1].type = SHARED;
  2688.         strcpy(scp[1].name, "white");
  2689.             }
  2690.      else {
  2691.         /* this window is not on a device that supports palettes */
  2692.         }
  2693.      ReleaseDC(w->window->iconwin, hdc);
  2694.          }
  2695.       if (palette) {
  2696.          if (ResizePalette(palette, numColors + j) == 0) {
  2697.             return NULL;
  2698.             }
  2699.          for (ii = 0; ii < j; ii++) {
  2700.             if (GetPaletteEntries(p2, ii, 1, &pe) == 0) {
  2701.                return NULL;
  2702.            }
  2703.             SetPaletteEntries(palette, numColors++, 1, &pe);
  2704.             }
  2705.          }
  2706.       bmap = DIBToBitmap(dib, palette);
  2707.       pdib = GlobalLock(dib);
  2708.       *width = DIBWidth(pdib);
  2709.       *height = DIBHeight(pdib);
  2710.       GlobalUnlock(dib);
  2711.       DestroyDIB(dib);
  2712.       DeleteObject(p2);
  2713.       *status = 0;
  2714.       return bmap;
  2715.       }
  2716.    return NULL;
  2717.    }
  2718.  
  2719.  
  2720. char *get_mutable_name(wbp w, int mute_index)
  2721.    {
  2722.    char *tmp;
  2723.    PALETTEENTRY pe;
  2724.  
  2725.    if (-mute_index > numColors || scp[-mute_index].type != MUTABLE) {
  2726.       return NULL;
  2727.       }
  2728.  
  2729.    if (GetPaletteEntries(palette, -mute_index, 1, &pe) == 0) {
  2730.       return NULL;
  2731.       }
  2732.    tmp = scp[-mute_index].name;
  2733.    sprintf(tmp, "%d", mute_index);
  2734.    sprintf(tmp + strlen(tmp) + 1, "%d,%d,%d",
  2735.       (pe.peRed << 8) | 0xff, (pe.peGreen << 8) | 0xff, (pe.peBlue << 8) | 0xff);
  2736.    return tmp + strlen(tmp) + 1;
  2737.    }
  2738.  
  2739. int set_mutable(wbp w, int i, char *s)
  2740.    {
  2741.    long r, g, b;
  2742.    UINT rv;
  2743.    PALETTEENTRY pe;
  2744.    if (palette == 0) return Failed;
  2745.  
  2746.    {
  2747.    STDLOCALS(w);
  2748.    if (parsecolor(w, s, &r, &g, &b) != Succeeded) {
  2749.       FREE_STDLOCALS(w);
  2750.       return Failed;                        /* invalid color specification */
  2751.       }
  2752.    pe.peRed = r >> 8;
  2753.    pe.peGreen = g >> 8;
  2754.    pe.peBlue = b >> 8;
  2755.    pe.peFlags = PC_RESERVED;
  2756.    raiseWindow(w);    /* mutable won't mutate if window isn't active */
  2757. #if 1
  2758.    AnimatePalette(palette, -i, 1, &pe);
  2759.    rv = SetPaletteEntries(palette, -i, 1, &pe);
  2760. #endif
  2761.    UnrealizeObject(palette);
  2762.    RealizePalette(stddc);
  2763.    AnimatePalette(palette, -i, 1, &pe);
  2764.    FREE_STDLOCALS(w);
  2765. }
  2766.    return Succeeded;
  2767.    }
  2768.  
  2769. void free_mutable(wbp w, int mute_index)
  2770.    {
  2771.    }
  2772.  
  2773. /*
  2774.  * Allocate a mutable color
  2775.  */
  2776. int mutable_color(wbp w, dptr argv, int argc, int *retval)
  2777.    {
  2778.    long r, g, b;
  2779.    tended char *str;
  2780.    LOGPALETTE lp;
  2781.    {
  2782.    STDLOCALS(w);
  2783.  
  2784.    if (!stddc || ((GetDeviceCaps(stddc, RASTERCAPS) & RC_PALETTE) == 0)) {
  2785.       FREE_STDLOCALS(w);
  2786.       return Failed;
  2787.       }
  2788.  
  2789.    numColors++;
  2790.    scp = realloc(scp, numColors * sizeof(struct wcolor));
  2791.    if (scp == NULL) {
  2792.       FREE_STDLOCALS(w);
  2793.       return Failed;
  2794.       }
  2795.    scp[numColors-1].c = -(numColors-1);
  2796.    sprintf(scp[numColors-1].name, "%d:", -(numColors-1));
  2797.    scp[numColors-1].type = MUTABLE;
  2798.    if (ResizePalette(palette, numColors) == 0) {
  2799.       FREE_STDLOCALS(w);
  2800.       return Failed;
  2801.       }
  2802.  
  2803.    if (argc > 0) {                     /* set the color */
  2804.       if (argc != 1) {
  2805.          FREE_STDLOCALS(w);
  2806.          return Error;
  2807.          }
  2808.       /*
  2809.        * old-style check for C integer
  2810.        */
  2811.       else if (argv[0].dword == D_Integer) {/* check for color cell */
  2812.      if (IntVal(argv[0]) >= 0) {
  2813.             FREE_STDLOCALS(w);
  2814.         return Failed;        /* must be negative */
  2815.             }
  2816.      if (GetPaletteEntries(palette, -IntVal(argv[0]),
  2817.         1, lp.palPalEntry) == 0) {
  2818.             FREE_STDLOCALS(w);
  2819.             return Error;
  2820.             }
  2821.      /* convert to linear color? */
  2822.      }
  2823.       else {
  2824.      if (!cnv:C_string(argv[0],str)) {
  2825.             FREE_STDLOCALS(w);
  2826.         ReturnErrVal(103,argv[0], Error);
  2827.         }
  2828.      if (parsecolor(w, str, &r, &g, &b) != Succeeded) {
  2829.         /* reduce logical palette size and count */
  2830.             FREE_STDLOCALS(w);
  2831.         numColors--;
  2832.             ResizePalette(palette, numColors);
  2833.         return Failed;                   /* invalid color specification */
  2834.         }
  2835.      lp.palPalEntry[0].peRed = r >> 8;
  2836.      lp.palPalEntry[0].peGreen = g >> 8;
  2837.      lp.palPalEntry[0].peBlue = b >> 8;
  2838.      }
  2839.       lp.palNumEntries = 1;
  2840.       lp.palVersion = 0x300;
  2841.       lp.palPalEntry[0].peFlags = PC_RESERVED;
  2842.       SetPaletteEntries(palette, numColors - 1, 1, lp.palPalEntry);
  2843.       UnrealizeObject(palette);
  2844.       RealizePalette(stddc);
  2845.       }
  2846.  
  2847.    *retval = -(numColors - 1);
  2848.    FREE_STDLOCALS(w);
  2849.    return Succeeded;
  2850.    }
  2851.    }
  2852.  
  2853. void freecolor(wbp w, char *s)
  2854.    {
  2855.    }
  2856.  
  2857. /*
  2858.  * drawarcs() - assumes x and y are already fixed up for the bitmap
  2859.  */
  2860. void drawarcs(wbp wb, XArc *arcs, int narcs)
  2861.    {
  2862.    register XArc *arc = arcs;
  2863.    int i, halfwidth, halfheight, x1, y1, x2, y2, right, bottom;
  2864.    double a1_a2;
  2865.    HPEN hp, oldpen, oldpen2;
  2866.    STDLOCALS(wb);
  2867.    hp = CreatePenIndirect(&(wc->pen));
  2868.    if (stdwin) oldpen = SelectObject(stddc, hp);
  2869.    oldpen2 = SelectObject(pixdc, hp);
  2870.    for (i = 0; i < narcs; i++, arc++) {
  2871.       halfwidth = arc->width >> 1;
  2872.       halfheight = arc->height >> 1;
  2873.       arc->angle1 = -arc->angle1 - arc->angle2;
  2874.       a1_a2 = arc->angle1 + arc->angle2;
  2875.       x1 = arc->x + halfwidth + (int)(halfwidth * cos(arc->angle1));
  2876.       y1 = arc->y + halfheight - (int)(halfheight * sin(arc->angle1));
  2877.       x2 = arc->x + halfwidth + (int)(halfwidth * cos(a1_a2));
  2878.       y2 = arc->y + halfheight - (int)(halfheight * sin(a1_a2));
  2879.       right = arc->x + arc->width + 1;
  2880.       bottom = arc->y + arc->height + 1;
  2881.       if (ws->win)
  2882.      Arc(stddc, arc->x, arc->y, right, bottom, x1, y1, x2, y2);
  2883.       Arc(pixdc, arc->x, arc->y, right, bottom, x1, y1, x2, y2);
  2884.       }
  2885.    if (stdwin) SelectObject(stddc, oldpen);
  2886.    SelectObject(pixdc, oldpen2);
  2887.    DeleteObject(hp);
  2888.    FREE_STDLOCALS(wb);
  2889.    return;
  2890.    }
  2891.  
  2892.  
  2893. /*
  2894.  * drawlines - Support routine for DrawLine
  2895.  */
  2896. void drawlines(wbinding *wb, XPoint *points, int npoints)
  2897.    {
  2898.    int i, diff, bheight;
  2899.    HPEN hp, oldpen, oldpen2;
  2900.    XPoint tmp[2];
  2901.    STDLOCALS(wb);
  2902.    hp = CreatePenIndirect(&(wc->pen));
  2903.    if (stdwin) oldpen = SelectObject(stddc, hp);
  2904.    oldpen2 = SelectObject(pixdc, hp);
  2905.    tmp[0] = points[npoints-1];
  2906.    tmp[1] = points[npoints-2];
  2907.    if (ws->win) {
  2908.       SetBkMode(stddc, wc->bkmode);
  2909.       Polyline(stddc, points, npoints);
  2910.       Polyline(stddc, tmp, 2);
  2911.       }
  2912.    SetBkMode(pixdc, wc->bkmode);
  2913.    Polyline(pixdc, points, npoints);
  2914.    Polyline(pixdc, tmp, 2);
  2915.    if (stdwin) SelectObject(stddc, oldpen);
  2916.    SelectObject(pixdc, oldpen2);
  2917.    DeleteObject(hp);
  2918.    FREE_STDLOCALS(wb);
  2919.    return;
  2920.    }
  2921.  
  2922.  
  2923. /*
  2924.  * drawpoints() -
  2925.  *  Parameters - the window binding for output, an array of points (assumed
  2926.  *               to be fixed up for bitmap) and the number of points
  2927.  */
  2928. void drawpoints(wbinding *wb, XPoint *points, int npoints)
  2929.    {
  2930.    register XPoint *p, *endp;
  2931.    SysColor palfg;
  2932.    STDLOCALS(wb);
  2933.    endp = points + npoints;
  2934.    palfg = PALCLR(wc->fg);
  2935.    if (stdwin) {
  2936.       for(p = points; p < endp; p++) {
  2937.          SetPixel(stddc, p->x, p->y, palfg);
  2938.          SetPixel(pixdc, p->x, p->y, palfg);
  2939.          }
  2940.       }
  2941.    else {
  2942.       for(p = points; p < endp; p++) {
  2943.          SetPixel(pixdc, p->x, p->y, palfg);
  2944.          }
  2945.       }
  2946.    FREE_STDLOCALS(wb);
  2947.    return;
  2948.    }
  2949.  
  2950.  
  2951. /*
  2952.  * drawsegments() -
  2953.  */
  2954. void drawsegments(wbinding *wb, XSegment *segs, int nsegs)
  2955.    {
  2956.    int i, bheight;
  2957.    XPoint ps[2];
  2958.    HPEN hp, oldpen, oldpen2;
  2959.    STDLOCALS(wb);
  2960.    hp = CreatePenIndirect(&(wc->pen));
  2961.    if (stdwin) oldpen = SelectObject(stddc, hp);
  2962.    oldpen2 = SelectObject(pixdc, hp);
  2963.    if (stdwin) {
  2964.       SetBkMode(stddc, wc->bkmode);
  2965.       for (i = 0; i < nsegs; i++) {
  2966.      Polyline(stddc, (POINT *)(segs+i), 2);
  2967.      }
  2968.       }
  2969.    SetBkMode(pixdc, wc->bkmode);
  2970.    for (i = 0; i < nsegs; i++) {
  2971.       Polyline(pixdc, (POINT *)(segs+i), 2);
  2972.       }
  2973.    if (stdwin) SelectObject(stddc, oldpen);
  2974.    SelectObject(pixdc, oldpen2);
  2975.    DeleteObject(hp);
  2976.    FREE_STDLOCALS(wb);
  2977.    return;
  2978.    }
  2979.  
  2980.  
  2981. int allowresize(w, on)
  2982. wbp w;
  2983. int on;
  2984.    {
  2985.    if (on)
  2986.       SETRESIZABLE(w);
  2987.    else
  2988.       CLRRESIZABLE(w);
  2989.    return Succeeded;
  2990.    }
  2991. int getselection(wbp w, char *buf)
  2992. {
  2993.    return Failed;
  2994.    }
  2995. int setselection(wbp w, char *val)
  2996. {
  2997.    return Failed;
  2998.    }
  2999.  
  3000. /*
  3001.  * drawstrng()
  3002.  */
  3003. void drawstrng(wbinding *wb, int x, int y, char *s, int slen)
  3004.    {
  3005.    STDLOCALS(wb);
  3006.  
  3007.    STDFONT;
  3008.    if (stdwin) {
  3009.       SetBkMode(stddc, TRANSPARENT);
  3010.       if (wc->fg != RGB(0, 0, 0)) SetTextColor(stddc, PALCLR(wc->fg));
  3011.       if (wc->bg != RGB(255, 255, 255)) SetBkColor(stddc, PALCLR(wc->bg));
  3012.       TextOut(stddc, x, y - ASCENT(wb), s, slen);
  3013.       }
  3014.    SetBkMode(pixdc, TRANSPARENT);
  3015.    if (wc->fg != RGB(0, 0, 0)) SetTextColor(pixdc, PALCLR(wc->fg));
  3016.    if (wc->bg != RGB(255, 255, 255)) SetBkColor(pixdc, PALCLR(wc->bg));
  3017.    TextOut(pixdc, x, y - ASCENT(wb), s, slen);
  3018.  
  3019.    FREE_STDLOCALS(wb);
  3020.    return;
  3021.    }
  3022.  
  3023.  
  3024. /*
  3025.  * fillarcs
  3026.  */
  3027. void fillarcs(wbp wb, XArc *arcs, int narcs)
  3028.    {
  3029.    register XArc *arc = arcs;
  3030.    int i, diff, bheight;
  3031.    HBRUSH hb, oldbrush, oldbrush2;
  3032.    POINT pts[3];
  3033.    HPEN hp, oldpen, oldpen2;
  3034.    STDLOCALS(wb);
  3035.    hp = CreatePenIndirect(&(wc->pen));
  3036.    if (stdwin) oldpen = SelectObject(stddc, hp);
  3037.    oldpen2 = SelectObject(pixdc, hp);
  3038.    hb = CreateBrushIndirect(&(wc->brush));
  3039.    if (stdwin) oldbrush = SelectObject(stddc, hb);
  3040.    oldbrush2 = SelectObject(pixdc, hb);
  3041.    SetTextColor(pixdc, PALCLR(wc->fg));
  3042.    if (stdwin) SetTextColor(stddc, PALCLR(wc->fg));
  3043.    SetBkColor(pixdc, PALCLR(wc->bg));
  3044.    if (stdwin) SetBkColor(stddc, PALCLR(wc->bg));
  3045.    if (stdwin) SetBkMode(stddc, wc->bkmode);
  3046.    SetBkMode(pixdc, wc->bkmode);
  3047.    for (i = 0; i < narcs; i++, arc++) {
  3048.       if (arc->angle2 >= 2 * Pi) {
  3049.          /*
  3050.           * from SDK reference: Ellipse() draws up to but not including
  3051.           * the right and bottom coordinates.  Add +1 to compensate.
  3052.           */
  3053.      if (stdwin)
  3054.         Ellipse(stddc, arc->x, arc->y,
  3055.             arc->x + arc->width + 1, arc->y + arc->height + 1);
  3056.      Ellipse(pixdc, arc->x, arc->y,
  3057.          arc->x + arc->width + 1, arc->y + arc->height + 1);
  3058.      }
  3059.       else {
  3060.      arc->angle1 = -arc->angle1 - arc->angle2;
  3061.      pts[0].x = arc->x + (arc->width>>1);
  3062.      pts[0].y = arc->y + (arc->height>>1);
  3063.      pts[1].x = arc->x + (arc->width>>1) +
  3064.             (int)(((arc->width + 1)>>1) * cos(arc->angle1));
  3065.      pts[1].y = arc->y + (arc->height>>1) -
  3066.             (int)(((arc->height )>>1) * sin(arc->angle1));
  3067.      pts[2].x = arc->x + (arc->width>> 1) +
  3068.             (int)(((arc->width + 1)>>1) * cos(arc->angle1+arc->angle2));
  3069.      pts[2].y = arc->y + (arc->height>>1) -
  3070.             (int)(((arc->height )>>1) * sin(arc->angle1+arc->angle2));
  3071.      if (stdwin) {
  3072.         Pie(stddc, arc->x, arc->y,
  3073.         arc->x + arc->width + 1, arc->y + arc->height + 1,
  3074.         pts[1].x, pts[1].y, pts[2].x, pts[2].y);
  3075.         }
  3076.      Pie(pixdc, arc->x, arc->y,
  3077.          arc->x + arc->width + 1, arc->y + arc->height + 1,
  3078.         pts[1].x, pts[1].y, pts[2].x, pts[2].y);
  3079.      }
  3080.       }
  3081.    if (stdwin) SelectObject(stddc, oldpen);
  3082.    SelectObject(pixdc, oldpen2);
  3083.    DeleteObject(hp);
  3084.    if (stdwin) SelectObject(stddc, oldbrush);
  3085.    SelectObject(pixdc, oldbrush2);
  3086.    DeleteObject(hb);
  3087.    FREE_STDLOCALS(wb);
  3088.    return;
  3089.    }
  3090.  
  3091. /*
  3092.  * fillrectangles
  3093.  */
  3094. void fillrectangles(wbp wb, XRectangle *recs, int nrecs)
  3095.    {
  3096.    int i, diff, bheight;
  3097.    HBRUSH hb, oldbrush, oldbrush2;
  3098.    HPEN hp, oldpen, oldpen2;
  3099.    STDLOCALS(wb);
  3100.    hp = CreatePenIndirect(&(wc->pen));
  3101.    if (stdwin) oldpen = SelectObject(stddc, hp);
  3102.    oldpen2 = SelectObject(pixdc, hp);
  3103.    hb = CreateBrushIndirect(&(wc->brush));
  3104.    if (stdwin) oldbrush = SelectObject(stddc, hb);
  3105.    oldbrush2 = SelectObject(pixdc, hb);
  3106.    SetTextColor(pixdc, PALCLR(wc->fg));
  3107.    if (stdwin) SetTextColor(stddc, PALCLR(wc->fg));
  3108.    SetBkColor(pixdc, PALCLR(wc->bg));
  3109.    if (stdwin) SetBkColor(stddc, PALCLR(wc->bg));
  3110.    if (stdwin) SetBkMode(stddc, wc->bkmode);
  3111.    SetBkMode(pixdc, wc->bkmode);
  3112.    for (i = 0; i < nrecs; i++) {
  3113.       recs[i].right += recs[i].left;
  3114.       recs[i].bottom += recs[i].top;
  3115.       if (stdwin) FillRect(stddc, (recs+i), hb);
  3116.       FillRect(pixdc, (recs+i), hb);
  3117.       }
  3118.    if (stdwin) SelectObject(stddc, oldpen);
  3119.    SelectObject(pixdc, oldpen2);
  3120.    DeleteObject(hp);
  3121.    if (stdwin) SelectObject(stddc, oldbrush);
  3122.    SelectObject(pixdc, oldbrush2);
  3123.    DeleteObject(hb);
  3124.    FREE_STDLOCALS(wb);
  3125.    return;
  3126.    }
  3127.  
  3128.  
  3129. /*
  3130.  * drawrectangles - draw nrecs # of rectangles in array recs to binding w
  3131.  */
  3132. void drawrectangles(wbp w, XRectangle *recs, int nrecs)
  3133.    {
  3134.    register XRectangle *r;
  3135.    LOGBRUSH lb;
  3136.    HBRUSH hb, oldbrush, oldbrush2;
  3137.    HPEN hp, oldpen, oldpen2;
  3138.    STDLOCALS(w);
  3139.    hp = CreatePenIndirect(&(wc->pen));
  3140.    if (stdwin) oldpen = SelectObject(stddc, hp);
  3141.    oldpen2 = SelectObject(pixdc, hp);
  3142.    lb.lbStyle = BS_NULL;
  3143.    hb = CreateBrushIndirect(&lb);
  3144.    if (stdwin) oldbrush = SelectObject(stddc, hb);
  3145.    oldbrush2 = SelectObject(pixdc, hb);
  3146.    for (r = recs; r < recs + nrecs; r++) {
  3147.       /*
  3148.        * from SDK reference: Rectangle() draws up to but not including
  3149.        * the right and bottom coordinates.  Add +1 to compensate.
  3150.        */
  3151.       r->right += r->left + 1;
  3152.       r->bottom += r->top + 1;
  3153.       if (stdwin) Rectangle(stddc, r->left, r->top, r->right, r->bottom);
  3154.       Rectangle(pixdc, r->left, r->top, r->right, r->bottom);
  3155.       }
  3156.    if (stdwin) SelectObject(stddc, oldpen);
  3157.    SelectObject(pixdc, oldpen2);
  3158.    DeleteObject(hp);
  3159.    if (stdwin) SelectObject(stddc, oldbrush);
  3160.    SelectObject(pixdc, oldbrush2);
  3161.    DeleteObject(hb);
  3162.    FREE_STDLOCALS(w);
  3163.    return;
  3164.    }
  3165.  
  3166. /*
  3167.  * fillpolygon
  3168.  */
  3169. void fillpolygon(wbp w, XPoint *pts, int npts)
  3170.    {
  3171.    HBRUSH hb, oldbrush;
  3172.    HPEN hp, oldpen, oldpen2;
  3173.    STDLOCALS(w);
  3174.    if (stdwin) SetBkMode(stddc, wc->bkmode);
  3175.    SetBkMode(pixdc, wc->bkmode);
  3176.    hp = CreatePenIndirect(&(wc->pen));
  3177.    if (stdwin) oldpen = SelectObject(stddc, hp);
  3178.    oldpen2 = SelectObject(pixdc, hp);
  3179.    hb = CreateBrushIndirect(&(wc->brush));
  3180.    if (stdwin) {
  3181.       oldbrush = SelectObject(stddc, hb);
  3182.       Polygon(stddc, pts, npts);
  3183.       SelectObject(stddc, oldbrush);
  3184.       }
  3185.    oldbrush = SelectObject(pixdc, hb);
  3186.    Polygon(pixdc, pts, npts);
  3187.    SelectObject(pixdc, oldbrush);
  3188.    DeleteObject(hb);
  3189.    if (stdwin) SelectObject(stddc, oldpen);
  3190.    SelectObject(pixdc, oldpen2);
  3191.    DeleteObject(hp);
  3192.    FREE_STDLOCALS(w);
  3193.    }
  3194.  
  3195. LONG NumWindows = 0;
  3196.  
  3197.  
  3198. /*
  3199.  * allocate a context.  Can't be called until w has a display and window.
  3200.  */
  3201. wcp alc_context(w)
  3202. wbp w;
  3203.    {
  3204.    int i;
  3205.    wcp wc;
  3206.  
  3207.    GRFX_ALLOC(wc, _wcontext);
  3208.  
  3209.    wc->bkmode = OPAQUE;        /* at present, only used in line drawing */
  3210.    wc->fg = RGB(0,0,0);
  3211.    wc->bg = RGB(255,255,255);
  3212.    wc->fgname = salloc("black");
  3213.    wc->bgname = salloc("white");
  3214.    wc->pen.lopnStyle = PS_SOLID;
  3215.    wc->pen.lopnWidth.x = wc->pen.lopnWidth.y = 1;
  3216.    wc->pen.lopnColor = PALCLR(wc->fg);
  3217.    wc->bgpen.lopnStyle = PS_SOLID;
  3218.    wc->bgpen.lopnWidth.x = wc->bgpen.lopnWidth.y = 1;
  3219.    wc->bgpen.lopnColor = PALCLR(wc->bg);
  3220.    wc->fillstyle = BS_SOLID;
  3221.    wc->brush.lbStyle = BS_SOLID;
  3222.    wc->brush.lbColor = PALCLR(wc->fg);
  3223.    wc->bgbrush.lbStyle = BS_SOLID;
  3224.    wc->bgbrush.lbColor = PALCLR(wc->bg);
  3225.    wc->gamma = GammaCorrection;
  3226.    wc->drawop = R2_COPYPEN;
  3227.    wc->font = (wfp)alloc(sizeof (struct _wfont));
  3228.    wc->font->name = salloc("fixed");
  3229.    wc->font->font = CreateFont(16,0,0,0,FW_NORMAL,0,0,0,
  3230.      ((MAXBYTESPERCHAR==1)?ANSI_CHARSET:DEFAULT_CHARSET),
  3231.      OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
  3232.      DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
  3233.      getenv("ICONFONT"));
  3234.  
  3235.    wc->font->charwidth = 8; /* looks like a bug */
  3236.    wc->leading = 16;
  3237.  
  3238.    GRFX_LINK(wc, wcntxts);
  3239.    return wc;
  3240.    }
  3241.  
  3242. /*
  3243.  * allocate a context, cloning attributes from an existing context
  3244.  */
  3245. wcp clone_context(w)
  3246. wbp w;
  3247.    {
  3248.    wcp wc, wc2 = w->context;
  3249.    wsp ws = w->window;
  3250.    wbinding tmp;
  3251.    int i;
  3252.  
  3253.    GRFX_ALLOC(wc, _wcontext);
  3254.  
  3255.    tmp.window = ws;
  3256.    tmp.context = wc;
  3257.    /*
  3258.     * copy over some stuff
  3259.     */
  3260.    wc->clipx = wc2->clipx;
  3261.    wc->clipy = wc2->clipy;
  3262.    wc->clipw = wc2->clipw;
  3263.    wc->cliph = wc2->cliph;
  3264.    if (wc2->cliprgn)
  3265.       wc->cliprgn = CreateRectRgn(wc->clipx,wc->clipy,
  3266.             wc->clipx+wc->clipw,
  3267.             wc->clipy+wc->cliph);
  3268.    wc->dx = wc2->dx;
  3269.    wc->dy = wc2->dy;
  3270.    wc->bits = wc2->bits;
  3271.    /*
  3272.     * clone needs to make a copy of the pattern
  3273.     *   if (wc2->pattern) {
  3274.     *      wc->pattern = copy+somehow(wc2->pattern);
  3275.     *      if (wc2->patternname)
  3276.     *         wc->patternname = salloc(wc2->patternname);
  3277.     *      }
  3278.     */
  3279.  
  3280.    wc->bkmode = wc2->bkmode;
  3281.    wc->fg = wc2->fg;
  3282.    wc->bg = wc2->bg;
  3283.    wc->fgname = salloc(wc2->fgname);
  3284.    wc->bgname = salloc(wc2->bgname);
  3285.    wc->pen = wc2->pen;
  3286.    if (ISXORREVERSEW(wc)) {
  3287.       wc->brush.lbColor = PALCLR((wc->fg ^ wc->bg) & 0x00FFFFFF);
  3288.       }
  3289.    else {
  3290.       wc->brush.lbColor = PALCLR(wc->fg);
  3291.       }
  3292.    wc->bgpen = wc2->bgpen;
  3293.    wc->fillstyle = wc2->fillstyle;
  3294.    wc->brush.lbStyle = wc->fillstyle;
  3295.    wc->bgbrush.lbStyle = wc->fillstyle;
  3296.    wc->bgbrush.lbColor = PALCLR(wc->bg);
  3297.    wc->gamma = wc2->gamma;
  3298.    wc->drawop = wc2->drawop;
  3299.    wc->font = (wfp)alloc(sizeof (struct _wfont));
  3300.    wc->font->name = salloc("fixed");
  3301.    wc->font->font = CreateFont(13,0,0,0,FW_NORMAL,0,0,0,
  3302.      ((MAXBYTESPERCHAR==1)?ANSI_CHARSET:DEFAULT_CHARSET),
  3303.      OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
  3304.      DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
  3305.      getenv("ICONFONT"));
  3306.    wc->leading = wc2->leading;
  3307.    setfont(&tmp, &(wc2->font->name));
  3308.  
  3309.    GRFX_LINK(wc, wcntxts);
  3310.    return wc;
  3311.    }
  3312.  
  3313. /*
  3314.  * allocate a window state structure
  3315.  */
  3316. wsp alc_winstate()
  3317.    {
  3318.    int i;
  3319.    wsp ws;
  3320.  
  3321.    GRFX_ALLOC(ws, _wstate);
  3322.    ws->bits = 1024;                             /* echo ON; others OFF */
  3323.    ws->filep = nulldesc;
  3324.    ws->listp = nulldesc;
  3325.    ws->cursorname = salloc("arrow");
  3326.    ws->curcursor = LoadCursor(NULL, IDC_ARROW);
  3327.    GRFX_LINK(ws, wstates);
  3328.    return ws;
  3329.    }
  3330.  
  3331. /*
  3332.  * free a window state
  3333.  */
  3334. int free_window(ws)
  3335. wsp ws;
  3336.    {
  3337.    int i;
  3338.    ws->refcount--;
  3339.    if(ws->refcount == 0) {
  3340.       if (ws->win) /* && IsWindowVisible(ws->win))*/
  3341.      DestroyWindow(ws->win);
  3342. /*      ws->win = 0;*/
  3343.       if (ws->iconwin && ws->iconwin != ws->win) {
  3344.          if (IsWindowVisible(ws->iconwin))
  3345.         DestroyWindow(ws->iconwin);
  3346.          else DestroyWindow(ws->iconwin);
  3347.      }
  3348. /*      ws->iconwin = 0;*/
  3349. /*      while (ws->win)
  3350.      if (pollevent() == -1) return -1;
  3351. */
  3352.       if (ws->windowlabel) free(ws->windowlabel);
  3353.       if (ws->iconlabel) free(ws->iconlabel);
  3354.       if (ws->pix)
  3355.      DeleteObject(ws->pix);
  3356.       ws->pix = 0;
  3357.       if (ws->iconpix)
  3358.      DeleteObject(ws->iconpix);
  3359.       ws->iconpix = 0;
  3360.       if (ws->initialPix)
  3361.      DeleteObject(ws->initialPix);
  3362.       ws->initialPix = 0;
  3363.       /* need to enumerate and specifically free each string */
  3364.       if (ws->menuMap) {
  3365.      for(i=0;i<ws->nmMapElems;i++) free(ws->menuMap[i]);
  3366.          free(ws->menuMap);
  3367.          ws->menuMap = 0;
  3368.      }
  3369.       free(ws->cursorname);
  3370.       if (ws->child) {
  3371.          for(i=0;i<ws->nChildren;i++) {
  3372.             free(ws->child[i].id);
  3373.             if (ws->child[i].font) DeleteObject(ws->child[i].font);
  3374.         }
  3375.          free(ws->child);
  3376.      }
  3377.       ws->child = 0;
  3378.       GRFX_UNLINK(ws, wstates);
  3379.       }
  3380.    return 0;
  3381.    }
  3382.  
  3383. /*
  3384.  * free a window context
  3385.  */
  3386. void free_context(wc)
  3387. wcp wc;
  3388.    {
  3389.    wc->refcount--;
  3390.    if(wc->refcount == 0) {
  3391.       if (wc->cliprgn)
  3392.      DeleteObject(wc->cliprgn);
  3393.       wc->cliprgn = 0;
  3394.       if (wc->pattern)
  3395.      DeleteObject(wc->pattern);
  3396.       wc->pattern = 0;
  3397.       if (wc->patternname)
  3398.      free(wc->patternname);
  3399.       wc->patternname = 0;
  3400.       if (wc->fgname) free(wc->fgname);
  3401.       wc->fgname = 0;
  3402.       if (wc->bgname) free(wc->bgname);
  3403.       wc->bgname = 0;
  3404.       if (wc->font) {
  3405.      if (wc->font->font)
  3406.         DeleteObject(wc->font->font);
  3407.      wc->font->font = 0;
  3408.      if (wc->font->name)
  3409.         free(wc->font->name);
  3410.      wc->font->name = 0;
  3411.      free(wc->font);
  3412.      }
  3413.       wc->font = 0;
  3414.       GRFX_UNLINK(wc, wcntxts);
  3415.       }
  3416.    }
  3417.  
  3418. int walert(wbp w, int volume)
  3419.    {
  3420.    MessageBeep(0);
  3421.    }
  3422.  
  3423. int patbits[] = {
  3424.   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  3425.   0xFE,0xFF,0xEF,0xFF,0xFE,0xFF,0xEF,0xFF,
  3426.   0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,
  3427.   0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,
  3428.   0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,
  3429.   0x01,0x00,0x10,0x00,0x01,0x00,0x10,0x00,
  3430.   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  3431.  
  3432.   0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
  3433.   0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,
  3434.   0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,
  3435.   0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x10,
  3436.   0x82,0x44,0x28,0x10,0x28,0x44,0x82,0x01,
  3437.  
  3438.   0x0F,0x0F,0x0F,0x0F,0xF0,0xF0,0xF0,0xF0,
  3439.   0x1B,0x18,0x81,0xB1,0x36,0x06,0x60,0x63,
  3440.   0x02,0x02,0x05,0xF8,0x20,0x20,0x50,0x8F,
  3441.   0x03,0x84,0x48,0x30,0x03,0x84,0x48,0x30,
  3442. };
  3443.  
  3444. /*
  3445.  * SetPattern
  3446.  */
  3447. int SetPattern(w, name, len)
  3448. wbp w;
  3449. char *name;
  3450. int len;
  3451.    {
  3452.    int width, nbits;
  3453.    int i, j;
  3454.    int symbol;
  3455.    C_integer v, bits[MAXXOBJS];
  3456.    HBITMAP p;
  3457.    char data[MAXXOBJS];
  3458.    char *buf = data;
  3459.    wcp wc = w->context;
  3460.  
  3461.    if (wc->patternname != NULL)
  3462.       free(wc->patternname);
  3463.    wc->patternname = malloc(len+1);
  3464.    strncpy(wc->patternname, name, len);
  3465.    wc->patternname[len] = '\0';
  3466.  
  3467.    /*
  3468.     * If the pattern starts with a number it is a width , bits encoding
  3469.     */
  3470.    if ((len > 0) && isdigit(name[0])) {
  3471.       nbits = MAXXOBJS;
  3472.       switch (parsepattern(name, len, &width, &nbits, bits)) {
  3473.       case Failed:
  3474.      return Failed;
  3475.       case Error:
  3476.      ReturnErrNum(145, Error);
  3477.      }
  3478.       if (w->window->iconwin == NULL) return Succeeded;
  3479.       return SetPatternBits(w, width, bits, nbits);
  3480.       }
  3481.  
  3482.    /*
  3483.     * Otherwise, it is a named pattern.  Find the symbol id.
  3484.     */
  3485.    if ((symbol = si_s2i(siPatternSyms, wc->patternname)) >= 0) {
  3486.       if (w->window->iconwin == NULL) return Succeeded;
  3487.       for(i = 0; i < 8; i++) {
  3488.      v = reversebits(~(patbits[symbol * 8 + i]));
  3489.      *buf++ = v;
  3490.      }
  3491.       p = CreateBitmapFromData(data);
  3492.       if (wc->pattern)
  3493.      DeleteObject(wc->pattern);
  3494.       wc->pattern = p;
  3495.       if (wc->fillstyle == BS_PATTERN) {
  3496.      wc->brush.lbStyle = BS_PATTERN;
  3497.      wc->brush.lbColor = PALCLR(wc->fg);
  3498.      wc->brush.lbHatch = (LONG)p;
  3499.      }
  3500.       return Succeeded;
  3501.       }
  3502.    ReturnErrNum(145, Error);
  3503.    }
  3504.  
  3505. /*
  3506.  * Create an 8x8 bitmap from some data
  3507.  */
  3508. HBITMAP CreateBitmapFromData(char *data)
  3509. {
  3510.    WORD *wBits = alloc(8 * sizeof(WORD));
  3511.    HBITMAP rv;
  3512.    int i;
  3513.    static BITMAP bitmap = { 0, 8, 8, 2, 1, 1};
  3514.    for (i = 0; i < 8; i++)
  3515.       wBits[i] = data[i];
  3516.    bitmap.bmBits = (LPSTR) wBits;
  3517.    rv = CreateBitmapIndirect(&bitmap);
  3518.    free(wBits);
  3519.    return rv;
  3520. }
  3521.  
  3522.  
  3523. int SetPatternBits(w, width, bits, nbits)
  3524. wbp w;
  3525. int width;
  3526. C_integer *bits;
  3527. int nbits;
  3528.    {
  3529.    C_integer v;
  3530.    int i, j, k;
  3531.    HBITMAP p;
  3532.    char data[MAXXOBJS];
  3533.    char *buf = data;
  3534.    wcp wc = w->context;
  3535.  
  3536.    if (width != nbits)
  3537.       return Failed;
  3538.  
  3539.    if (width == 8) {
  3540.       for(i = 0; i < nbits; i++) {
  3541.          v = bits[i];
  3542.      *buf++ = reversebits(~v);
  3543.      }
  3544.       }
  3545.    else if (width == 4) {
  3546.       for(k=0; k < 2; k++) /* do twice to get 8 rows */
  3547.       for(i = 0; i < nbits; i++) {
  3548.          v = widenbits(bits[i]);
  3549.      *buf++ = reversebits(~v);
  3550.      }
  3551.       }
  3552.    else return Failed;
  3553.  
  3554.    p = CreateBitmapFromData(data);
  3555.    if (wc->pattern)
  3556.       DeleteObject(wc->pattern);
  3557.    wc->pattern = p;
  3558.    if (wc->fillstyle == BS_PATTERN) {
  3559.       wc->brush.lbStyle = BS_PATTERN;
  3560.       wc->brush.lbColor = PALCLR(wc->fg);
  3561.       wc->brush.lbHatch = (LONG)p;
  3562.       }
  3563.    return Succeeded;
  3564.    }
  3565.  
  3566. int widenbits(int c)
  3567. {
  3568.    int rv = c;
  3569.    if (c & 1) rv |= 16;
  3570.    if (c & 2) rv |= 32;
  3571.    if (c & 4) rv |= 64;
  3572.    if (c & 8) rv |= 128;
  3573.    return rv;
  3574. }
  3575.  
  3576. int reversebits(int c)
  3577. {
  3578.   int rv = 0;
  3579.   if (c & 1) rv |= 128;
  3580.   if (c & 2) rv |= 64;
  3581.   if (c & 4) rv |= 32;
  3582.   if (c & 8) rv |= 16;
  3583.   if (c & 16) rv |= 8;
  3584.   if (c & 32) rv |= 4;
  3585.   if (c & 64) rv |= 2;
  3586.   if (c & 128) rv |= 1;
  3587.   return rv;
  3588. }
  3589.  
  3590. int pixmap_init(w)
  3591. wbp w;
  3592.    {
  3593.    wsp ws = w->window;
  3594.    resizePixmap(w, ws->width, ws->height);
  3595.    return Succeeded;
  3596.    }
  3597.  
  3598.  
  3599. int do_config(w, status)
  3600. wbp w;
  3601. int status;
  3602.    {
  3603.    wsp ws = w->window;
  3604.    int wid = ws->width, ht = ws->height;
  3605.    int posx = ws->posx, posy = ws->posy;
  3606.    if (! resizePixmap(w, wid, ht))
  3607.       return Failed;
  3608.    if (ws->win) {
  3609.       pollevent();
  3610.       if (status == 3) {
  3611.      SetWindowPos(ws->win, ws->win,
  3612.               posx,
  3613.               posy,
  3614.               wid, ht, SWP_NOZORDER);
  3615.      }
  3616.       else if (status == 2) {
  3617.      SetWindowPos(ws->win, ws->win, 0, 0,
  3618.               wid, ht, SWP_NOMOVE|SWP_NOZORDER);
  3619.          }
  3620.       else if (status == 1)
  3621.      SetWindowPos(ws->win, ws->win,
  3622.               posx,
  3623.               posy,
  3624.               0, 0, SWP_NOSIZE|SWP_NOZORDER);
  3625.       }
  3626.    else if (ws->iconwin) {
  3627.       if (status == 3) {
  3628.      SetWindowPos(ws->iconwin, ws->iconwin,
  3629.               posx,
  3630.               posy,
  3631.               wid, ht, SWP_NOZORDER);
  3632.      }
  3633.       else if (status == 2) {
  3634.      SetWindowPos(ws->iconwin, ws->iconwin, 0, 0,
  3635.               wid, ht, SWP_NOMOVE|SWP_NOZORDER);
  3636.          }
  3637.       else if (status == 1)
  3638.      SetWindowPos(ws->iconwin, ws->iconwin,
  3639.               posx,
  3640.               posy,
  3641.               0, 0, SWP_NOSIZE|SWP_NOZORDER);
  3642.       }
  3643.    return Succeeded;
  3644.    }
  3645.  
  3646. DWORD playMIDIfile(HWND hWndNotify, LPSTR s)
  3647. {
  3648.    UINT wDeviceID;
  3649.    DWORD dwReturn;
  3650.    MCI_OPEN_PARMS mciOpenParms;
  3651.    MCI_PLAY_PARMS mciPlayParms;
  3652.    MCI_STATUS_PARMS mciStatusParms;
  3653.    MCI_SEQ_SET_PARMS mciSeqSetParms;
  3654.  
  3655.    mciOpenParms.lpstrDeviceType = "sequencer";
  3656.    mciOpenParms.lpstrElementName = s;
  3657.    if (dwReturn = mciSendCommand((UINT)NULL, MCI_OPEN,
  3658.                  MCI_OPEN_TYPE | MCI_OPEN_ELEMENT,
  3659.                  (DWORD)(LPVOID) &mciOpenParms)) {
  3660.       return dwReturn;
  3661.       }
  3662.    wDeviceID = mciOpenParms.wDeviceID;
  3663.  
  3664.    /* attempt to select the MIDI mapper */
  3665.    mciSeqSetParms.dwPort = MIDI_MAPPER;
  3666.    if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SEQ_SET_PORT,
  3667.                  (DWORD)(LPVOID) &mciSeqSetParms)) {
  3668.       /* could not select the MIDI mapper; play anyway */
  3669.       }
  3670.  
  3671.    mciPlayParms.dwCallback = (DWORD) hWndNotify;
  3672.    if (dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY,
  3673.          (DWORD)(LPVOID) &mciPlayParms)) {
  3674.       mciSendCommand(wDeviceID, MCI_CLOSE, 0, (DWORD)NULL);
  3675.       return dwReturn;
  3676.       }
  3677.  
  3678.    return 0L;
  3679. }
  3680.  
  3681.  
  3682. int playmedia(wbp w, char *s)
  3683. {
  3684.    if (strstr(s, ".wav") || strstr(s, ".WAV")) {
  3685.       sndPlaySound((LPSTR) s, SND_ASYNC);
  3686.       return Succeeded;
  3687.       }
  3688.    else if (strstr(s, ".mid") || strstr(s, ".MID") ||
  3689.             strstr(s, ".rmi") || strstr(s, ".RMI")) {
  3690.       if (playMIDIfile(w->window->win, (LPSTR) s) == 0)
  3691.          return Succeeded;
  3692.       }
  3693.    /*
  3694.     * Interpret as an MCI command string
  3695.     */
  3696.    else {
  3697.       if (mciSendString(s, NULL, 0, 0L)) return Failed;
  3698.       return Succeeded;
  3699.       }
  3700. }
  3701.  
  3702. /*
  3703.  * UpdateCursorPos
  3704.  */
  3705. void UpdateCursorPos(wsp ws, wcp wc)
  3706. {
  3707.    if (ISCURSORONW(ws)) {
  3708.       if (ws->hasCaret) {
  3709.          }
  3710.       CreateCaret(ws->iconwin, NULL, FWIDTHC(wc), FHEIGHTC(wc));
  3711.       SetCaretBlinkTime(500);
  3712.       SetCaretPos(ws->x, ws->y - ASCENTC(wc));
  3713.       ShowCaret(ws->iconwin);
  3714.       ws->hasCaret = 1;
  3715.       }
  3716. }
  3717.  
  3718. int resizePixmap(wbp w, int width, int height)
  3719.    {
  3720.    HDC hdc, hdc2, hdc3;
  3721.    HBITMAP newpix, oldpix, oldpix2;
  3722.    HBRUSH hb;
  3723.    LOGBRUSH lb;
  3724.    XRectangle rect;
  3725.    wsp ws = w->window;
  3726.    int x = ws->pixwidth, y = ws->pixheight;
  3727.    if (ISEXPOSED(w)) {
  3728.       if (ws->pixwidth >= width && ws->pixheight >= height) {
  3729.          return 1;
  3730.          }
  3731.       ws->pixheight = max(ws->pixheight, height);
  3732.       ws->pixwidth = max(ws->pixwidth, width);
  3733.       }
  3734.    else {
  3735.       ws->pixwidth = width;
  3736.       ws->pixheight = height;
  3737.       }
  3738.    hdc = GetDC(ws->iconwin);
  3739.    newpix = CreateCompatibleBitmap (hdc, ws->pixwidth, ws->pixheight);
  3740.    if (ws->pix) {
  3741.       hdc2 = CreateCompatibleDC(hdc);
  3742.       oldpix = SelectObject(hdc2, ws->pix);
  3743.       }
  3744.    hdc3 = CreateCompatibleDC(hdc);
  3745.    oldpix2 = SelectObject(hdc3, newpix);
  3746.    if (palette) {
  3747.       SelectPalette(hdc, palette, FALSE);
  3748.       if (ws->pix) SelectPalette(hdc2, palette, FALSE);
  3749.       SelectPalette(hdc3, palette, FALSE);
  3750.       RealizePalette(hdc);
  3751.       if (ws->pix) RealizePalette(hdc2);
  3752.       RealizePalette(hdc3);
  3753.       }
  3754.    lb.lbStyle = BS_SOLID;
  3755.    lb.lbColor = PALCLR(w->context->bg);
  3756.    hb = CreateBrushIndirect(&lb);
  3757.    /*
  3758.     * initialize the new pixmap, including areas not in the old pixmap.
  3759.     */
  3760.    rect.left = 0; rect.right = ws->pixwidth;
  3761.    rect.top = 0; rect.bottom = ws->pixheight;
  3762.    FillRect(hdc3, &rect, hb);
  3763.    if (ws->win)
  3764.       FillRect(hdc, &rect, hb);
  3765.  
  3766.    if (ws->pix) BitBlt(hdc3, 0, 0, x - 2, y - 1, hdc2, 0, 0, SRCCOPY);
  3767.    if (ws->win)
  3768.       BitBlt(hdc, 0, 0, ws->pixwidth, ws->pixheight, hdc3, 0, 0, SRCCOPY);
  3769.    SelectObject(hdc3, oldpix2);
  3770.    DeleteDC(hdc3);
  3771.    if (ws->pix) {
  3772.       SelectObject(hdc2, oldpix);
  3773.       DeleteDC(hdc2);
  3774.       }
  3775.    ReleaseDC(ws->iconwin, hdc);
  3776.    if (ws->pix) DeleteObject(ws->pix);
  3777.    DeleteObject(hb);
  3778.    ws->pix = newpix;
  3779.    return 1;
  3780.    }
  3781.  
  3782. /*
  3783.  * CreateWinDC - create a device context for drawing on the window
  3784.  *  In addition, select objects specified by flags.
  3785.  */
  3786. HDC CreateWinDC(wbp w)
  3787.    {
  3788.    wsp ws = w->window;
  3789.    wcp wc = w->context;
  3790.    HDC hdc = GetDC(ws->iconwin);
  3791.    if (numColors > 0) {
  3792.       SelectPalette(hdc, palette, FALSE);
  3793. /*      UnrealizeObject(palette); */
  3794.       RealizePalette(hdc);
  3795.       if (numRealized < numColors) {
  3796.          numRealized = numColors;
  3797.          if (RealizePalette(hdc) == 0) /* noop */;
  3798.          }
  3799.       }
  3800.    SetROP2(hdc, wc->drawop);
  3801.    if (wc->clipw >= 0){
  3802.       SelectClipRgn(hdc, wc->cliprgn);
  3803.       }
  3804.    return hdc;
  3805.    }
  3806.  
  3807. HDC CreatePixDC(wbp w, HDC hdc)
  3808.    {
  3809.    wsp ws = w->window;
  3810.    wcp wc = w->context;
  3811.    HBITMAP oldpix;
  3812.    HDC hdc2 = CreateCompatibleDC(hdc);
  3813.    if (numColors > 0) {
  3814.       SelectPalette(hdc2, palette, FALSE);
  3815.       RealizePalette(hdc2);
  3816.       }
  3817. /*   ws->initialPix = */ ws->theOldPix = SelectObject(hdc2, ws->pix);
  3818.    SetROP2(hdc2, wc->drawop);
  3819.    if (wc->clipw >= 0){
  3820.       SelectClipRgn(hdc2, wc->cliprgn);
  3821.       }
  3822.    return hdc2;
  3823.    }
  3824.  
  3825. int setinputmask(wbp w, char *val)
  3826. {
  3827.    wsp ws = w->window;
  3828.    if (strchr(val,'m')) {
  3829.       ws->inputmask |= PointerMotionMask;
  3830.       }
  3831.    else {
  3832.       ws->inputmask &= ~PointerMotionMask;
  3833.       }
  3834.    return Succeeded;
  3835. }
  3836.  
  3837. int dc_maxcharwidth(HDC dc)
  3838. {
  3839.   int i, m = -1, x;
  3840.   char s[2];
  3841.   s[1] = '\0';
  3842.   for (i=0; i<256; i++) {
  3843.     s[0] = i;
  3844.     x = dc_textwidth(dc, s, 1);
  3845.     if (x > m) m = x;
  3846.   }
  3847.   return m;
  3848. }
  3849.  
  3850. /*
  3851.  * compute a text width for a current device context (typically pixdc)
  3852.  */
  3853. int dc_textwidth(HDC dc, char *s, int n)
  3854. {
  3855.    SIZE sz;
  3856.    /*
  3857.     * GetTextExtentPoint32(dc, s, n, &sz) gives incorrect behavior
  3858.     *  under Win32s
  3859.     */
  3860.    GetTextExtentPoint(dc, s, n, &sz);
  3861.    return (int)sz.cx;
  3862. }
  3863.  
  3864. int sysScrollWidth()
  3865. {
  3866.    return GetSystemMetrics(SM_CXVSCROLL);
  3867. }
  3868.  
  3869. int sysFontHeight(wbp w)
  3870. {
  3871.    TEXTMETRIC tm;
  3872.    int rv;
  3873.    wsp ws = w->window;
  3874.    HDC dc = GetDC(ws->iconwin);
  3875.    HFONT oldfont = SelectObject(dc, GetStockObject(SYSTEM_FIXED_FONT));
  3876.    GetTextMetrics(dc, &tm);
  3877.    SelectObject(dc, oldfont);
  3878.    ReleaseDC(ws->iconwin, dc);
  3879.    return tm.tmHeight + tm.tmExternalLeading;
  3880. }
  3881.  
  3882. int sysTextWidth(wbp w, char *s, int n)
  3883. {
  3884.    int rv;
  3885.    wsp ws = w->window;
  3886.    HDC dc = GetDC(ws->iconwin);
  3887.    HFONT oldfont;
  3888.    oldfont = SelectObject(dc, GetStockObject(SYSTEM_FIXED_FONT));
  3889.    rv = dc_textwidth(dc, s, n);
  3890.    SelectObject(dc, oldfont);
  3891.    ReleaseDC(ws->iconwin, dc);
  3892.    return rv;
  3893. }
  3894.  
  3895. int textWidth(wbp w, char *s, int n)
  3896.    {
  3897.    int rv;
  3898.    wsp ws = w->window;
  3899.    HDC stddc = GetDC(ws->iconwin);
  3900.    HFONT oldfont = SelectObject(stddc, w->context->font->font);
  3901.    rv = dc_textwidth(stddc, s, n);
  3902.    SelectObject(stddc, oldfont);
  3903.    ReleaseDC(ws->iconwin, stddc);
  3904.    return rv;
  3905.    }
  3906.  
  3907. void warpPointer(w, x, y)
  3908. wbp w;
  3909. int x, y;
  3910.    {
  3911.    wsp ws = w->window;
  3912.    SetCursorPos(ws->posx + x, ws->posy + y);
  3913.    }
  3914.  
  3915. /*
  3916.  * free all Windows resources allocated by this instantiation of iconx
  3917.  */
  3918. void wfreersc()
  3919. {
  3920.    wbp w;
  3921.    extern struct palentry *palsetup_palette;
  3922.    while (wbndngs != NULL) {
  3923.       w = wbndngs;
  3924.       wbndngs = wbndngs->next;
  3925.       free(w);
  3926.       }
  3927.    while (wstates != NULL) {
  3928.       wstates->refcount = 1;
  3929.       free_window(wstates);
  3930.       }
  3931.    while (wcntxts != NULL) {
  3932.       wcntxts->refcount = 1;
  3933.       free_context(wcntxts);
  3934.       }
  3935.    if (palette) {
  3936.       DeleteObject(palette);
  3937.       palette = 0;
  3938.       }
  3939.    if (palsetup_palette) {
  3940.       free(palsetup_palette);
  3941.       palsetup_palette = 0;
  3942.       }
  3943.    if (scp) {
  3944.       free(scp);
  3945.       scp = 0;
  3946.       }
  3947.    if (wlhead)
  3948.       wlfree();
  3949.    mciSendCommand(MCI_ALL_DEVICE_ID, MCI_CLOSE, 0, (DWORD)NULL);
  3950. }
  3951.  
  3952.  
  3953. /*
  3954.  * Native Windows UI facilities
  3955.  */
  3956. void makebutton(wsp ws, childcontrol *cc, char *s)
  3957. {
  3958.    cc->type = CHILD_BUTTON;
  3959.    cc->font = 0;
  3960.    cc->id = salloc(s);
  3961.    cc->win = CreateWindow("button", cc->id,
  3962.              WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
  3963.          0, 0, 0, 0, ws->iconwin, (HMENU)ws->nChildren, mswinInstance,
  3964.          NULL);
  3965. }
  3966.  
  3967. void makescrollbar(wsp ws, childcontrol *cc, char *s, int i1, int i2)
  3968. {
  3969.    cc->type = CHILD_SCROLLBAR;
  3970.    cc->id = salloc(s);
  3971.    cc->font = 0;
  3972.    cc->win = CreateWindow("scrollbar", cc->id,
  3973.             WS_CHILD | WS_VISIBLE | SBS_VERT, 0, 0, 0, 0,
  3974.         ws->iconwin, (HMENU)ws->nChildren, mswinInstance, NULL);
  3975.    SetScrollRange(cc->win, SB_CTL, i1, i2, FALSE);
  3976. }
  3977.  
  3978. int nativemenubar(wbp w, int total, int argc, dptr argv, int warg, dptr d)
  3979. {
  3980.    wsp ws;
  3981.    tended struct b_list *hp;
  3982.    HMENU tempMenu, tempMenu2 = NULL;
  3983.    tended char *s, *s2;
  3984.    int r, i;
  3985.    ws = w->window;
  3986.  
  3987.    if (ws->nmMapElems)
  3988.       tempMenu2 = ws->menuBar;
  3989.  
  3990.    ws->menuBar = CreateMenu();
  3991.    ws->nmMapElems = total;
  3992.    total = 0;
  3993.    while (warg < argc){
  3994.       /*
  3995.        * each argument must be a list of strings
  3996.        */
  3997.       hp = (struct b_list *)BlkLoc(argv[warg]);
  3998.       r = hp->size;
  3999.       /*
  4000.        * Construct a Windows menu corresponding to the Icon list
  4001.        */
  4002.       tempMenu = CreateMenu();
  4003.       for(i=0; i < r; i++) {
  4004.          c_get(hp, d);
  4005.          if (!is:string(*d)) return Error;
  4006.          if (!cnv:C_string(*d, s)) return Error;
  4007.          s = strdup(s);
  4008.          if (i == 0) s2=s;
  4009.          else
  4010.             AppendMenu(tempMenu, MF_STRING, total, s);
  4011.          ws->menuMap[total++] = s;
  4012.          c_put(&(argv[warg]), d);
  4013.          }
  4014.       AppendMenu(ws->menuBar, MF_POPUP, (unsigned int)tempMenu, s2);
  4015.       warg++;
  4016.       }
  4017.    /*
  4018.     * Insert the menu into the window
  4019.     */
  4020.    if (ws->win) SetMenu(ws->win, ws->menuBar);
  4021.    if (tempMenu2) {
  4022.       int i, n = GetMenuItemCount(tempMenu2);
  4023.       for (i=0; i < n; i++) {
  4024.          DestroyMenu(GetSubMenu(tempMenu2, i));
  4025.          }
  4026.       DestroyMenu(tempMenu2);
  4027.       }
  4028.    return Succeeded;
  4029. }
  4030.  
  4031. void makeeditregion(wbp w, childcontrol *cc, char *s)
  4032. {
  4033.    wsp ws = w->window;
  4034.    cc->type = CHILD_EDIT;
  4035.    cc->id = salloc(s);
  4036.    cc->win = CreateWindow("edit", NULL,
  4037.         WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |
  4038.         WS_BORDER | ES_LEFT | ES_MULTILINE |
  4039.         ES_AUTOHSCROLL | ES_AUTOVSCROLL,
  4040.         0, 0, 0, 0, ws->iconwin,
  4041.         (HMENU) ws->nChildren, mswinInstance, NULL);
  4042.    setchildfont(cc, w->context->font->name);
  4043. }
  4044.  
  4045. void cleareditregion(childcontrol *cc)
  4046. {
  4047.    SendMessage(cc->win, WM_CLEAR, 0, 0);
  4048. }
  4049.  
  4050. void copyeditregion(childcontrol *cc)
  4051. {
  4052.    SendMessage(cc->win, WM_COPY, 0, 0);
  4053. }
  4054.  
  4055. void cuteditregion(childcontrol *cc)
  4056. {
  4057.    SendMessage(cc->win, WM_CUT, 0, 0);
  4058. }
  4059.  
  4060. void pasteeditregion(childcontrol *cc)
  4061. {
  4062.    SendMessage(cc->win, WM_PASTE, 0, 0);
  4063. }
  4064.  
  4065. int undoeditregion(childcontrol *cc)
  4066. {
  4067.    if (!SendMessage(cc->win, WM_UNDO, 0, 0)) return Failed;
  4068.    return Succeeded;
  4069. }
  4070.  
  4071. int modifiededitregion(childcontrol *cc)
  4072. {
  4073.    if (!SendMessage(cc->win, EM_GETMODIFY, 0, 0)) return Failed;
  4074.    return Succeeded;
  4075. }
  4076.  
  4077. int setmodifiededitregion(childcontrol *cc, int i)
  4078. {
  4079.    SendMessage(cc->win, EM_SETMODIFY, i, 0);
  4080.    return Succeeded;
  4081. }
  4082.  
  4083. void geteditregion(childcontrol *cc, dptr d)
  4084. {
  4085.    int y = GetWindowTextLength(cc->win);
  4086.    char *s2 = alcstr(NULL, y + 1);
  4087.    GetWindowText(cc->win, s2, y+1);
  4088.    StrLoc(*d) = s2;
  4089.    StrLen(*d) = y;
  4090. }
  4091.  
  4092. void seteditregion(childcontrol *cc, char *s2)
  4093. {
  4094.    SetWindowText(cc->win, s2);
  4095. }
  4096.  
  4097.  
  4098. void movechild(childcontrol *cc,
  4099.            C_integer x, C_integer y, C_integer width, C_integer height)
  4100. {
  4101.    MoveWindow(cc->win, x, y, width, height, TRUE);
  4102. }
  4103.  
  4104. int setchildfont(childcontrol *cc, char *fontname)
  4105. {
  4106.    HFONT hf;
  4107.    RECT rect;
  4108.    if (hf = mkfont(fontname)) {
  4109.       SendMessage(cc->win, WM_SETFONT, (WPARAM)hf, 0);
  4110.       if (cc->font) DeleteObject(cc->font);
  4111.       cc->font = hf;
  4112.       GetClientRect(cc->win, &rect);
  4113.       InvalidateRect(cc->win, &rect, TRUE);
  4114.       return Succeeded;
  4115.       }
  4116.    return Failed;
  4117. }
  4118.  
  4119. void setfocusonchild(wsp ws, childcontrol *cc, int width, int height)
  4120. {
  4121.    if (width || height) {
  4122.       SetFocus(cc->win);
  4123.       ws->focusChild = cc->win;
  4124.       }
  4125.    else ws->focusChild = 0;
  4126. }
  4127.  
  4128. void setchildselection(wsp ws, childcontrol *cc, int x, int y)
  4129. {
  4130.    int iLine = SendMessage(cc->win, EM_LINEFROMCHAR, x-1,0);
  4131.    int topLine = SendMessage(cc->win, EM_GETFIRSTVISIBLELINE, 0, 0);
  4132.    if (topLine != iLine) {
  4133.       SendMessage(cc->win, EM_LINESCROLL, 0, iLine-topLine);
  4134.       }
  4135.    SendMessage(cc->win, EM_SETSEL, x - 1, y - 1);
  4136.    SetFocus(cc->win);
  4137.    ws->focusChild = cc->win;
  4138. }
  4139.  
  4140. CHOOSEFONT cf;
  4141. LOGFONT lf;
  4142.  
  4143. int nativefontdialog(wbp w, char *buf, int flags, int fheight)
  4144. {
  4145.    strcpy(lf.lfFaceName, buf);
  4146.    lf.lfHeight = fheight;
  4147.    lf.lfWidth = 0;
  4148.    lf.lfEscapement = 0;
  4149.    if (!strcmp(lf.lfFaceName, "mono") || !strcmp(lf.lfFaceName, "fixed")){
  4150.       strcpy(lf.lfFaceName, "Lucida Sans Typewriter");
  4151.       flags |= FONTFLAG_MONO + FONTFLAG_SANS;
  4152.       }
  4153.    else if (!strcmp(lf.lfFaceName, "typewriter")) {
  4154.       strcpy(lf.lfFaceName, "courier");
  4155.       flags |= FONTFLAG_MONO + FONTFLAG_SERIF;
  4156.       }
  4157.    else if (!strcmp(lf.lfFaceName, "sans")) {
  4158.       strcpy(lf.lfFaceName, "swiss");
  4159.       flags |= FONTFLAG_PROPORTIONAL + FONTFLAG_SANS;
  4160.       }
  4161.    else if (!strcmp(lf.lfFaceName, "serif")) {
  4162.       strcpy(lf.lfFaceName, "roman");
  4163.       flags |= FONTFLAG_PROPORTIONAL + FONTFLAG_SERIF;
  4164.       }
  4165.  
  4166.    if (flags & FONTFLAG_BOLD) lf.lfWeight = FW_BOLD;
  4167.    else
  4168.       lf.lfWeight = FW_DONTCARE;
  4169.    if (flags & FONTFLAG_ITALIC) lf.lfItalic = 1;
  4170.    lf.lfUnderline = lf.lfStrikeOut = 0;
  4171.    lf.lfCharSet =
  4172.      ((MAXBYTESPERCHAR==1)?ANSI_CHARSET:DEFAULT_CHARSET);
  4173.    lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
  4174.    lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  4175.    lf.lfQuality = DEFAULT_QUALITY;
  4176.    if (FONTFLAG_PROPORTIONAL)
  4177.       lf.lfPitchAndFamily = VARIABLE_PITCH;
  4178.    else if (FONTFLAG_MONO)
  4179.       lf.lfPitchAndFamily = FIXED_PITCH;
  4180.    else
  4181.       lf.lfPitchAndFamily = DEFAULT_PITCH;
  4182.    if (!strcmp(lf.lfFaceName, "swiss")) lf.lfPitchAndFamily |= FF_SWISS;
  4183.    else if (!strcmp(lf.lfFaceName, "roman"))
  4184.       lf.lfPitchAndFamily |= FF_ROMAN;
  4185.    else
  4186.       lf.lfPitchAndFamily |= FF_DONTCARE;
  4187.  
  4188.    memset(&cf, 0, sizeof(CHOOSEFONT));
  4189.    cf.lStructSize = sizeof(CHOOSEFONT);
  4190.    cf.hwndOwner   = w->window->iconwin;
  4191.    cf.lpLogFont = &lf;
  4192.    cf.Flags = CF_SCREENFONTS | CF_EFFECTS | CF_INITTOLOGFONTSTRUCT;
  4193.    cf.rgbColors = RGB(0,0,0);
  4194.    cf.nFontType = SCREEN_FONTTYPE;
  4195.    if (ChooseFont(&cf) == 0) return Failed;
  4196.    sprintf(buf, "%s,%d%s%s", lf.lfFaceName,
  4197.            ((lf.lfHeight > 0) ? lf.lfHeight : -lf.lfHeight),
  4198.            (lf.lfItalic ? ",italic" : ""),
  4199.        ((lf.lfWeight > 500) ? ",bold" : ""));
  4200.    return Succeeded;
  4201. }
  4202.  
  4203. /*
  4204.  * common dialog functions
  4205.  */
  4206. COLORREF aclrCust[16];
  4207. CHOOSECOLOR cc;
  4208.  
  4209. char *nativecolordialog(wbp w, long r, long g, long b, char *buf)
  4210. {
  4211.    aclrCust[0] = RGB(255,255,255);
  4212.    aclrCust[1] = RGB(239,239,239);
  4213.    aclrCust[2] = RGB(223,223,223);
  4214.    aclrCust[3] = RGB(207,207,207);
  4215.    aclrCust[4] = RGB(191,191,191);
  4216.    aclrCust[5] = RGB(175,175,175);
  4217.    aclrCust[6] = RGB(159,159,159);
  4218.    aclrCust[7] = RGB(143,143,143);
  4219.    aclrCust[8] = RGB(127,127,127);
  4220.    aclrCust[9] = RGB(111,111,111);
  4221.    aclrCust[10] = RGB(95,95,95);
  4222.    aclrCust[11] = RGB(79,79,79);
  4223.    aclrCust[12] = RGB(63,63,63);
  4224.    aclrCust[13] = RGB(47,47,47);
  4225.    aclrCust[14] = RGB(31,31,31);
  4226.    aclrCust[15] = RGB(15,15,15);
  4227.    memset(&cc, 0, sizeof(CHOOSECOLOR));
  4228.    cc.lStructSize = sizeof(CHOOSECOLOR);
  4229.    cc.hwndOwner   = w->window->iconwin;
  4230.    cc.lpCustColors = aclrCust;
  4231.    cc.rgbResult = mscolor(w, r, g, b);
  4232.    cc.Flags = CC_FULLOPEN | CC_RGBINIT;
  4233.    if (ChooseColor(&cc) == 0) {
  4234.       return NULL;
  4235.       }
  4236.    sprintf(buf, "%d,%d,%d", (RED(cc.rgbResult)<<8) | 0xFF,
  4237.       (GREEN(cc.rgbResult) << 8) | 0xFF,
  4238.       (BLUE(cc.rgbResult) << 8) | 0xFF);
  4239.    return buf;
  4240. }
  4241.  
  4242.  
  4243.  
  4244.  
  4245. char *nativeselectdialog(wbp w, struct b_list *L, char *s)
  4246. {
  4247.    int i, j, okflag=0, yesnoflag=0, cancelflag=0, retryflag=0, otherflag=0;
  4248.    tended struct b_list *hp = L;
  4249.    tended char *s1 = NULL;
  4250.    tended struct descrip d, d2;
  4251.    char s3[8];
  4252.    wsp ws = w->window;
  4253.    int lsize;
  4254.  
  4255.    if (hp == NULL) {
  4256.       okflag = 1;
  4257.       }
  4258.    else {
  4259.       BlkLoc(d2) = (union block *)hp;
  4260.       d2.dword = D_List;
  4261.       lsize  = hp->size;
  4262.  
  4263.       for(i=0; i < lsize; i++) {
  4264.          c_get(hp, &d);
  4265.          if (!cnv:C_string(d, s1)) return NULL;
  4266.          for(j=0; j<8; j++) {
  4267.             s3[j] = tolower(s1[j]);
  4268.             if (s3[j] == '\0') break;
  4269.             }
  4270.          if (!strcmp(s3, "ok")) okflag = 1;
  4271.          else if (!strcmp(s3, "okay")) okflag = 1;
  4272.          else if (!strcmp(s3, "no")) yesnoflag = MB_YESNO;
  4273.          else if (!strcmp(s3, "yes")) yesnoflag = MB_YESNO;
  4274.          else if (!strcmp(s3, "cancel")) cancelflag++;
  4275.          else if (!strcmp(s3, "retry")) retryflag = MB_RETRYCANCEL;
  4276.          else { otherflag++; return NULL; }
  4277.          c_put(&d2, &d);
  4278.          }
  4279.       }
  4280.    /*
  4281.     * validate flags
  4282.     */
  4283.    if (okflag && yesnoflag) return NULL;
  4284.    if (okflag && retryflag) return NULL;
  4285.    if (yesnoflag && retryflag) return NULL;
  4286.    if (retryflag && !cancelflag) return NULL;
  4287.  
  4288.    if (cancelflag) {
  4289.       if (okflag) {
  4290.          okflag = MB_OKCANCEL;
  4291.          }
  4292.       else if (yesnoflag) yesnoflag = MB_YESNOCANCEL;
  4293.       }
  4294.     else if (okflag) okflag = MB_OK;
  4295.  
  4296.    j = MessageBox((ws->focusChild ? ws->focusChild :
  4297.           (ws->win ? ws->win : ws->iconwin)),
  4298.            s, " ",
  4299.           okflag | yesnoflag | retryflag
  4300.           | (strchr(s, '!') ? MB_ICONEXCLAMATION :
  4301.          (strchr(s, '?') ? MB_ICONQUESTION : MB_ICONASTERISK)));
  4302.  
  4303.    switch (j) {
  4304.    case IDOK: return "Okay";
  4305.    case IDCANCEL: return "Cancel";
  4306.    case IDYES: return "Yes";
  4307.    case IDNO: return "No";
  4308.    case IDRETRY: return "Retry";
  4309.    default: return NULL;
  4310.       }
  4311. }
  4312.  
  4313. OPENFILENAME ofn;
  4314.  
  4315. char *nativeopendialog(wbp w, char *s1, char *s2, char *s3, int i, int j)
  4316. {
  4317.    char buf[128], buf2[64];
  4318.  
  4319.    memset(&ofn, 0, sizeof(OPENFILENAME));
  4320.    ofn.lStructSize = sizeof(OPENFILENAME);
  4321.    ofn.hwndOwner   = w->window->iconwin;
  4322.    ofn.lpstrFilter = s3;
  4323.    ofn.nFilterIndex = j;
  4324.    strcpy(buf, s2);
  4325.    ofn.lpstrFile = buf;
  4326.    ofn.nMaxFile = sizeof(buf);
  4327.    ofn.lpstrTitle = s1;
  4328.    ofn.lpstrFileTitle = buf2;
  4329.    ofn.nMaxFileTitle = sizeof(buf2);
  4330.    ofn.lpstrInitialDir = NULL;
  4331.    ofn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST;
  4332.    if (GetOpenFileName(&ofn) == 0) return NULL;
  4333.    return ofn.lpstrFile;
  4334. }
  4335.  
  4336.  
  4337. char *nativesavedialog(wbp w, char *s1, char *s2, char *s3, int i, int j)
  4338. {
  4339.    char buf[128], buf2[64];
  4340.    /*
  4341.     * Use the standard dialog to obtain a filename.
  4342.     */
  4343.    memset(&ofn, 0, sizeof(OPENFILENAME));
  4344.    ofn.lStructSize = sizeof(OPENFILENAME);
  4345.    ofn.hwndOwner   = w->window->iconwin;
  4346.    ofn.lpstrFilter = s3;
  4347.    ofn.nFilterIndex = j;
  4348.    strcpy(buf, s2);
  4349.    ofn.lpstrFile = buf;
  4350.    ofn.nMaxFile = sizeof(buf);
  4351.    ofn.lpstrTitle = s1;
  4352.    ofn.lpstrFileTitle = buf2;
  4353.    ofn.nMaxFileTitle = sizeof(buf2);
  4354.    ofn.lpstrInitialDir = NULL;
  4355.    ofn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST;
  4356.    if (GetSaveFileName(&ofn) == 0) return NULL;
  4357.    return ofn.lpstrFile;
  4358. }
  4359.  
  4360. /*
  4361.  * flush a window - noop under Windows
  4362.  */
  4363. void wflush(w)
  4364. wbp w;
  4365.    {
  4366.    }
  4367.  
  4368. #else                                   /* Graphics */
  4369.   static char aaa;
  4370. #endif                                  /* Graphics */
  4371.