home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v92.tgz / v92.tar / v92 / src / runtime / rmswin.ri < prev    next >
Text File  |  1996-03-22  |  71KB  |  3,015 lines

  1. /*
  2.  * rmswin.ri - Microsoft Windows-specific graphics interface code.
  3.  *
  4.  * Todo:
  5.  *   geticonpos
  6.  *   seticonimage
  7.  *   free_mutable
  8.  *   freecolor
  9.  *   UpdateCursorPos
  10.  *
  11.  * Untested:
  12.  *   toggle_fgbg
  13.  *   rebind
  14.  *   setpointer
  15.  *   getlinestyle
  16.  *   geticonic
  17.  *   getimstr
  18.  *   getfntnam
  19.  *   setgamma
  20.  *   dumpimage
  21.  *
  22.  * Blown off:
  23.  *   getpointername
  24.  *   setcursor
  25.  *   getvisual
  26.  *   getdefault
  27.  */
  28. #ifdef Graphics
  29.  
  30. void wfreersc();
  31. int alc_rgb(wbp w, SysColor rgb);
  32. int numRealized;
  33.  
  34. #ifndef min
  35. #define min(x,y) (((x) < (y))?(x):(y))
  36. #define max(x,y) (((x) > (y))?(x):(y))
  37. #endif                                  /* min */
  38. #define PALCLR(c) (c | 0x2000000L)
  39.  
  40. #define BORDHEIGHT 26
  41. #define BORDWIDTH 6
  42.  
  43. wclrp scp;
  44. HPALETTE palette;
  45. int numColors = 0;
  46.  
  47. char *szAppName = "Icon";
  48.  
  49. /*
  50.  * pattern symbols
  51.  */
  52. stringint siPatternSyms[] = {
  53.   {0,           16},
  54.   { "black",     0},
  55.   { "checkers",  12},
  56.   { "darkgray",  2},
  57.   { "diagonal",  8},
  58.   { "grains",    13},
  59.   { "gray",      3},
  60.   { "grid",      10},
  61.   { "horizontal",9},
  62.   { "lightgray", 4},
  63.   { "scales",    14},
  64.   { "trellis",   11},
  65.   { "vertical",  7},
  66.   { "verydark",  1},
  67.   { "verylight", 5},
  68.   { "waves",     15},
  69.   { "white",     6},
  70. };
  71.  
  72. /*
  73.  * draw ops
  74.  */
  75. stringint drawops[] = {
  76.    { 0, 16},
  77.    {"and",              R2_MASKPEN},
  78.    {"andInverted",      R2_MASKPENNOT},
  79.    {"andReverse",       R2_MASKNOTPEN},
  80.    {"clear",            R2_BLACK},
  81.    {"copy",             R2_COPYPEN},
  82.    {"copyInverted",     R2_NOTCOPYPEN},
  83.    {"equiv",            R2_NOTXORPEN},
  84.    {"invert",           R2_NOT},
  85.    {"nand",             R2_NOTMASKPEN},
  86.    {"noop",             R2_NOP},
  87.    {"nor",              R2_NOTMERGEPEN},
  88.    {"or",               R2_MERGEPEN},
  89.    {"orInverted",       R2_MERGEPENNOT},
  90.    {"orReverse",        R2_MERGENOTPEN},
  91.    {"set",              R2_WHITE},
  92.    {"xor",              R2_XORPEN},
  93. };
  94.  
  95.  
  96. /*
  97.  * line types
  98.  */
  99. stringint siLineTypes[] = {
  100.   {0, 6},
  101.   {"dashdotted",        PS_DASHDOT},
  102.   {"dashdotdotted",     PS_DASHDOTDOT},
  103.   {"dashed",            PS_DASH},
  104.   {"dotted",            PS_DOT},
  105.   {"solid",             PS_SOLID},
  106.   {"striped",           PS_DASH}
  107. };
  108.  
  109.  
  110. #define NUMSYSCURSORSYMS        5
  111. #define NUMCURSORSYMS           0
  112.  
  113.  
  114. HINSTANCE mswinInstance;
  115. int ncmdShow;
  116.  
  117. int mswinsystem(char *s)
  118. {
  119.    int i = WinExec(s, SW_SHOW);
  120.    Sleep(1000);
  121.    if ( i > 32 ) return 0; else return -1;
  122. }
  123.  
  124. /*
  125.  * wopen
  126.  */
  127. FILE *wopen(char *name, struct b_list *lp, dptr attr, int n, int *err_idx)
  128.    {
  129.    wbp w;
  130.    wsp ws;
  131.    wcp wc;
  132.    struct imgdata *imd;
  133.    char answer[256];
  134.    int i, r;
  135.    tended struct b_list *tlp;
  136.    tended struct descrip attrrslt;
  137.    HDC hdc, hdc2, hdc3;
  138.    TEXTMETRIC    metrics;
  139.    LOGPALETTE logpal[4]; /* really 1 + space for an extra palette entry */
  140.    HBRUSH brush;
  141.  
  142.    tlp = lp;
  143.  
  144.    /*
  145.     * allocate a binding, a window state, and a context
  146.     */
  147.    Protect(w = alc_wbinding(), return NULL);
  148.    Protect(w->window = alc_winstate(), { free_binding(w); return NULL; });
  149.    Protect(w->context = alc_context(w), { free_binding(w); return NULL; });
  150.    ws = w->window;
  151.    ws->listp.dword = D_List;
  152.    BlkLoc(ws->listp) = (union block *)lp;
  153.    ws->width = ws->height = 0;
  154.    wc = w->context;
  155.  
  156.    /*
  157.     * process the passed in attributes - by calling wattrib
  158.     */
  159.    for(i = 0; i < n; i++)
  160.       switch (wattrib(w, StrLoc(attr[i]), StrLen(attr[i]), &attrrslt,
  161.             answer)) {
  162.       case Failed:
  163.      wclose(w);
  164.      return NULL;
  165.       case Error:
  166.      /* think of something to do here */
  167.      break;
  168.      }
  169.  
  170.    /*
  171.     * set the title, defaulting to the "filename" supplied to open()
  172.     */
  173.    if (ws->windowlabel == NULL) ws->windowlabel = salloc(name);
  174.    if (ws->iconlabel == NULL) ws->iconlabel = salloc(name);
  175.  
  176.    ws->iconwin = CreateWindow( "iconx", ws->windowlabel, WS_OVERLAPPEDWINDOW,
  177.            ws->posx < 0 ? 0 : ws->posx,
  178.            ws->posy < 0 ? 0 : ws->posy,
  179.            ws->width == 0 ? 400 : ws->width + BORDWIDTH,
  180.            ws->height == 0 ? 400: ws->height + BORDHEIGHT,
  181.            NULL, NULL, mswinInstance, NULL);
  182.    hdc = GetDC(ws->iconwin);
  183.    if ((GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) && (numColors == 0)){
  184.       /* This window is on a device that supports palettes */
  185.       numColors = 2;
  186.       logpal[0].palNumEntries = 2;
  187.       logpal[0].palVersion = 0x300;
  188.       logpal[0].palPalEntry[0].peFlags = 0;
  189.       logpal[0].palPalEntry[0].peRed = 0;
  190.       logpal[0].palPalEntry[0].peGreen = 0;
  191.       logpal[0].palPalEntry[0].peBlue = 0;
  192.       logpal[0].palPalEntry[1].peFlags = 0;
  193.       logpal[0].palPalEntry[1].peRed = 255;
  194.       logpal[0].palPalEntry[1].peGreen = 255;
  195.       logpal[0].palPalEntry[1].peBlue = 255;
  196.       palette = CreatePalette(logpal);
  197.       if ((scp = malloc(2 * sizeof (struct wcolor))) == NULL) return NULL;
  198.       scp[0].c = RGB(0,0,0);
  199.       scp[0].type = SHARED;
  200.       strcpy(scp[0].name, "black");
  201.       scp[1].c = RGB(255,255,255);
  202.       scp[1].type = SHARED;
  203.       strcpy(scp[1].name, "white");
  204.       }
  205.    SelectObject(hdc, wc->font->font);
  206.    GetTextMetrics(hdc, &metrics);
  207.    wc->font->ascent = metrics.tmAscent;
  208.    wc->font->descent = metrics.tmDescent;
  209.    wc->font->charwidth = metrics.tmMaxCharWidth;
  210.    wc->font->height = metrics.tmHeight;
  211.    wc->leading = metrics.tmHeight;
  212.    ws->x = 0;
  213.    ws->y = ASCENT(w);
  214.    ws->y += w->context->dy;
  215.    ws->x += w->context->dx;
  216.    if (!ws->width || !ws->height) {
  217.       if (!ws->width) ws->width = FWIDTH(w) * 80;
  218.       if (!ws->height) ws->height = FHEIGHT(w) * 12;
  219.       SetWindowPos(ws->iconwin, ws->iconwin, ws->posx, ws->posy,
  220.               ws->width + BORDWIDTH, ws->height + BORDHEIGHT,
  221.               SWP_NOZORDER);
  222.       }
  223.    ws->pix = CreateCompatibleBitmap(hdc, ws->width, ws->height);
  224.    ReleaseDC(ws->iconwin, hdc);
  225.    if (alc_rgb(w, wc->fg) == Failed) {
  226.       return 0;
  227.       }
  228.    if (alc_rgb(w, wc->bg) == Failed) {
  229.       return 0;
  230.       }
  231.    ws->pixwidth = ws->width;
  232.    ws->pixheight = ws->height;
  233.    if (!ISTOBEHIDDEN(ws)) {
  234.       ws->win = ws->iconwin;
  235.       ShowWindow(ws->win, ncmdShow);
  236.       }
  237.    else ws->win = 0;
  238.  
  239.    if (ws->initialPix) {
  240.       hdc = GetDC(ws->iconwin);
  241.       hdc2 = CreateCompatibleDC(hdc);
  242.       SelectObject(hdc2, ws->pix);
  243.       hdc3 = CreateCompatibleDC(hdc);
  244.       SelectObject(hdc3, ws->initialPix);
  245.       BitBlt(hdc2, 0, 0, ws->width, ws->height, hdc3, 0, 0, SRCCOPY);
  246.       if (ws->win)
  247.          BitBlt(hdc, 0, 0, ws->width, ws->height, hdc3, 0, 0, SRCCOPY);
  248.       DeleteDC(hdc2);
  249.       DeleteDC(hdc3);
  250.       DeleteObject(ws->initialPix);
  251.       ws->initialPix = (HBITMAP) NULL;
  252.       }
  253.    else {
  254.       imd = &ws->initimage;
  255.       if (imd->width) {
  256.      r = strimage(w, 0, 0, imd->width, imd->height, imd->paltbl,
  257.               imd->data, (word)imd->width * (word)imd->height, 0);
  258.      free((pointer)imd->paltbl);
  259.      free((pointer)imd->data);
  260.      imd->width = 0;
  261.      if (r < 0)
  262.         return 0;
  263.      }
  264.       else {
  265.      RECT r;
  266.      hdc = GetDC(ws->iconwin);
  267.      hdc2 = CreateCompatibleDC(hdc);
  268.      SelectObject(hdc2, ws->pix);
  269.          r.left = r.top = 0;
  270.      r.right = ws->width;
  271.      r.bottom = ws->height;
  272.          if (palette) {
  273.             SelectPalette(hdc, palette, FALSE);
  274.             SelectPalette(hdc2, palette, FALSE);
  275.         RealizePalette(hdc);
  276.         RealizePalette(hdc2);
  277.         }
  278.          brush = CreateBrushIndirect(&(wc->bgbrush));
  279.          if (ws->win)
  280.             FillRect(hdc, &r, brush);
  281.          FillRect(hdc2, &r, brush);
  282.          DeleteObject(brush);
  283.      ReleaseDC(ws->iconwin, hdc);
  284.      DeleteDC(hdc2);
  285.      }
  286.       }
  287.    if (ws->win)
  288.       UpdateWindow(ws->win);
  289.  
  290.    return (FILE *)w;
  291.    }
  292.  
  293. int handle_config(wbp w, UINT msg, WPARAM wp, LPARAM lp)
  294.    {
  295.    struct descrip d;
  296.    wsp ws = w->window;
  297.  
  298.    if (wp == SIZE_MINIMIZED) {
  299.       if (ws->win) {
  300.          SetWindowText(ws->win, ws->iconlabel);
  301.          ws->win = NULL;
  302.      }
  303.       return 1;
  304.       }
  305.  
  306.    if (ws->win)
  307.       SetWindowText(ws->win, ws->windowlabel);
  308.    ws->win = ws->iconwin;
  309.  
  310.    /*
  311.     * make sure text cursor stays on-screen
  312.     */
  313.    ws->x = min(ws->x, LOWORD(lp) - FWIDTH(w));
  314.    ws->y = min(ws->y, HIWORD(lp));
  315.  
  316.    /*
  317.     * if it was not a resize, drop it
  318.     */
  319.    if (ws->width == LOWORD(lp) && ws->height == HIWORD(lp))
  320.       return 1;
  321.  
  322.    ws->width = LOWORD(lp);
  323.    ws->height = HIWORD(lp);
  324.    if (! resizePixmap(w, ws->width, ws->height)) return 0;
  325.    if (!ISEXPOSED(w)) {
  326.       SETEXPOSED(w);
  327.       return 1;
  328.       }
  329.    MakeInt(RESIZED, &d);
  330.    qevent(w->window, &d, ws->width, ws->height, ~(uword)0, 0);
  331.    return 1;
  332.    }
  333.  
  334. void handle_keypress(wbp wb, UINT msg, WPARAM wp, LPARAM lp, int meta)
  335.    {
  336.    wsp ws = wb->window;
  337.    DWORD dw;
  338.    LONG t;
  339.    WORD x, y;
  340.    struct descrip d;
  341.    int flags = 0;
  342.    StrLen(d) = 1;
  343.    StrLoc(d) = (char *)&allchars[FromAscii(wp) & 0xFF];
  344.    dw = GetMessagePos();
  345.    x = LOWORD(dw);
  346.    y = HIWORD(dw);
  347.    t = GetMessageTime();
  348.    if (GetKeyState(VK_CONTROL) < 0) flags |= ControlMask;
  349.    if (GetKeyState(VK_SHIFT) < 0) flags |= ShiftMask;
  350.  
  351.    if (meta) flags |= Mod1Mask;
  352.    qevent(ws, &d, x, y, t, flags);
  353.    }
  354.  
  355. void handle_mouse(wbp wb, UINT msg, WPARAM wp, LPARAM lp)
  356.    {
  357.    wsp ws = wb->window;
  358.    LONG t;
  359.    WORD x, y;
  360.    struct descrip d;
  361.    long flags = 0, eventcode;
  362.  
  363.    switch(msg) {
  364.    case WM_MOUSEMOVE: /* only called if one of these three cases is true */
  365.       if (MK_LBUTTON & wp)
  366.      eventcode = MOUSELEFTDRAG;
  367.       else if (MK_RBUTTON & wp)
  368.      eventcode = MOUSERIGHTDRAG;
  369.       else if (MK_MBUTTON & wp)
  370.      eventcode = MOUSEMIDDRAG;
  371.       break;
  372.    case WM_LBUTTONDOWN:
  373.       eventcode = MOUSELEFT;
  374.       break;
  375.    case WM_MBUTTONDOWN:
  376.       eventcode = MOUSEMID;
  377.       break;
  378.    case WM_RBUTTONDOWN:
  379.       eventcode = MOUSERIGHT;
  380.       break;
  381.    case WM_LBUTTONUP:
  382.       eventcode = MOUSELEFTUP;
  383.       break;
  384.    case WM_MBUTTONUP:
  385.       eventcode = MOUSEMIDUP;
  386.       break;
  387.    case WM_RBUTTONUP:
  388.       eventcode = MOUSERIGHTUP;
  389.       break;
  390.       }
  391.  
  392.    MakeInt(eventcode, &d);
  393.    x = LOWORD(lp);
  394.    y = HIWORD(lp);
  395. /*   t = GetMessageTime(); */
  396.  
  397.    if (MK_CONTROL & wp) flags |= ControlMask;
  398.    if (MK_SHIFT & wp) flags |= ShiftMask;
  399.  
  400.    qevent(ws, &d, x, y, t, flags);
  401.    }
  402.  
  403. LRESULT_CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
  404. {
  405.    HDC hdc, hdc2;
  406.    PAINTSTRUCT ps;
  407.    RECT rect;
  408.    wbp wb = NULL;
  409.    wsp ws = NULL;
  410.  
  411.    /*
  412.     * find a binding associated with the given window.
  413.     */
  414.    for (wb = wbndngs; wb; wb=wb->next) {
  415.       ws = wb->window;
  416.  
  417.       if (((ws->win == hwnd) || (ws->iconwin == hwnd) ||
  418.        (ws->pix == hwnd) || (ws->initialPix == hwnd))) break;
  419.       }
  420.    if (msg == WM_QUIT) {
  421.       wfreersc();
  422.       }
  423.    else if (!wb) {
  424.       /* 
  425.        * doesn't look like its for one of our windows, pass it to
  426.        * DefWindowProc and hope for the best.
  427.        */
  428.       }
  429.    else
  430.    switch(msg) {
  431.    case WM_PAINT:
  432.       hdc = BeginPaint(hwnd, &ps);
  433.       GetClientRect(hwnd, &rect);
  434.       if (IsIconic(hwnd)) {
  435.          HBRUSH hb = CreateBrushIndirect(&(wb->context->brush));
  436.      FrameRect(hdc, &rect, hb);
  437.      DeleteObject(hb);
  438.      DrawText(hdc, "Iconx", 5, &rect, DT_WORDBREAK);
  439.      }
  440.       else {
  441.      hdc2 = CreateCompatibleDC(hdc);
  442.      SelectObject(hdc2, ws->pix);
  443.      BitBlt(hdc, rect.left, rect.top,
  444.         rect.right - rect.left + 1, rect.bottom - rect.top + 1,
  445.         hdc2, rect.left, rect.top, SRCCOPY);
  446.      DeleteDC(hdc2);
  447.      }
  448.       EndPaint(hwnd, &ps);
  449.       return 0;
  450.    case WM_MOUSEMOVE:
  451.       if ( (MK_LBUTTON | MK_RBUTTON | MK_MBUTTON) & wp )
  452.       handle_mouse(wb,msg,wp,lp);
  453.       return 0;
  454.    case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: case WM_MBUTTONDOWN:
  455.    case WM_LBUTTONUP:   case WM_RBUTTONUP:   case WM_MBUTTONUP:
  456.       handle_mouse(wb,msg,wp,lp);
  457.       return 0;
  458.    case WM_CHAR:
  459.       handle_keypress(wb, msg, wp, lp, 0);
  460.       return 0;
  461.    case WM_SYSCHAR:
  462.       handle_keypress(wb, msg, wp, lp, 1);
  463.       break;
  464.    case WM_SIZE:
  465.       handle_config(wb, msg, wp, lp);
  466.       break;
  467.    case WM_MOVE:
  468.       wb->window->posx = LOWORD(lp);
  469.       wb->window->posy = HIWORD(lp);
  470.       break;
  471.    case WM_ACTIVATE:
  472.       if (wp == WA_INACTIVE && wb->window->hasCaret) {
  473.          HideCaret(wb->window->iconwin);
  474.          DestroyCaret();
  475.          wb->window->hasCaret = 0;
  476.          }
  477.       break;
  478.    case WM_KILLFOCUS:
  479.       if (wb->window->hasCaret) {
  480.          HideCaret(wb->window->iconwin);
  481.          DestroyCaret();
  482.          wb->window->hasCaret = 0;
  483.          }
  484.       break;
  485.    /* case WM_QUIT is handled prior to the switch*/
  486.    case WM_DESTROY:
  487.       if (wb->window->win == hwnd)
  488.      wb->window->win = NULL;
  489.       if (wb->window->iconwin == hwnd)
  490.      wb->window->iconwin = NULL;
  491.       if (wb->window->refcount > 0) {
  492.      PostQuitMessage(0);
  493.      return 0;
  494.      }
  495.       else if (wb->window->refcount < 0) {
  496.      wb->window->refcount = -wb->window->refcount;
  497.      }
  498.    }
  499.    return DefWindowProc(hwnd, msg, wp, lp);
  500. }
  501.  
  502. /*
  503.  * wclose - make sure the window goes away - no questions asked
  504.  */
  505. int wclose(wbp w)
  506.    {
  507.    wsp ws = w->window;
  508.    if (pollevent() == -1) return -1;
  509.    if (ws->win && ws->refcount > 1) {
  510.       /*
  511.        * Decrement refcount and negate it to tell the window procedure
  512.        * that we closed the window, not the user, so don't terminate.
  513.        */
  514.       ws->refcount--;
  515.       ws->refcount = -ws->refcount;
  516.       DestroyWindow(ws->win);
  517.       while (ws->win)
  518.      if (pollevent() == -1) return -1;
  519.       }
  520.    else {
  521.       free_binding(w);
  522.       }
  523.    return 1;
  524.    }
  525.  
  526. int pollevent()
  527.    {
  528.    wbp w;
  529.    MSG m;
  530.    extern jmp_buf mark_sj;
  531.  
  532.    /* some while PeekMessage loops here, maybe one per window ? */
  533.    while (PeekMessage(&m, NULL, 0, 0, PM_NOREMOVE)) {
  534.       if (GetMessage(&m, NULL, 0, 0) == 0) longjmp(mark_sj, -1);
  535.       if (TranslateMessage(&m) == 0) {
  536.      DispatchMessage(&m);
  537.      }
  538.       }
  539.    return 400;
  540.    }
  541.  
  542. /*
  543.  * write some text to both the window and the pixmap
  544.  */
  545. novalue xdis(w,s,n)
  546. register wbp w;
  547. char *s;
  548. int n;
  549.    {
  550.    XPoint pt;
  551.    HBRUSH hb;
  552.    XRectangle rect;
  553.    STDLOCALS(w);
  554.  
  555.    STDFONT;
  556.    rect.left = ws->x; rect.right = ws->x + dc_textwidth(pixdc, s, n);
  557.    rect.top = ws->y - ASCENT(w); rect.bottom = ws->y + DESCENT(w);
  558.  
  559.    /* skip resource allocation if we are offscreen */
  560.    if (!(rect.left > ws->width || rect.right < 0 ||
  561.        rect.top < 0 || rect.bottom > ws->height)) {
  562.  
  563.       hb = CreateBrushIndirect(&(wc->bgbrush));
  564.       if (stdwin) {
  565.          /*
  566.           *  SetBkColor() does not dither consistently with bgbrush;
  567.           *  erase the background beforehand and use transparent drawing
  568.           */
  569.          FillRect(stddc, &rect, hb);
  570.          SetBkMode(stddc, TRANSPARENT);
  571.          SetTextColor(stddc, PALCLR(wc->fg));
  572.          TextOut(stddc, ws->x, ws->y - ASCENT(w), s, n);
  573.          }
  574.       FillRect(pixdc, &rect, hb);
  575.       DeleteObject(hb);
  576.       SetBkMode(pixdc, TRANSPARENT);
  577.       SetTextColor(pixdc, PALCLR(wc->fg));
  578.       TextOut(pixdc, ws->x, ws->y - ASCENT(w), s, n);
  579. #if 0
  580.       if (palette) {
  581.          UnrealizeObject(palette);
  582.          RealizePalette(stddc);
  583.          }
  584. #endif
  585.       }
  586.    ws->x += dc_textwidth(pixdc, s, n);
  587.    
  588.    FREE_STDLOCALS(w);
  589.    }
  590. /*
  591.  * wputc
  592.  */
  593. int wputc(int ci, wbp w)
  594.    {
  595.    char c = (char)ci;
  596.    wsp ws = w->window;
  597.    wcp wc = w->context;
  598.    int y_plus_descent;
  599.    HBRUSH hb;
  600.  
  601.    switch (c) {
  602.    case '\n':
  603.       ws->y += LEADING(w);
  604.       if (ws->y + DESCENT(w) > ws->height) {
  605.      RECT r;
  606.      STDLOCALS(w);
  607.      ws->y -= LEADING(w);
  608.      y_plus_descent = ws->y + DESCENT(w);
  609.      BitBlt(pixdc, 0, 0,
  610.         ws->width, y_plus_descent,
  611.         pixdc, 0, LEADING(w), SRCCOPY);
  612.      r.left = 0;
  613.      r.top = y_plus_descent - FHEIGHT(w);
  614.      r.right = ws->width;
  615.      r.bottom = ws->height;
  616.          hb = CreateBrushIndirect(&(wc->bgbrush));
  617.      FillRect(pixdc, &r, hb);
  618.      DeleteObject(hb);
  619.      if (stdwin)
  620.         BitBlt(stddc, 0, 0, ws->width, ws->height,
  621.            pixdc, 0, 0, SRCCOPY);
  622.      FREE_STDLOCALS(w);
  623.      }
  624.       /* intended fall-through */
  625.     case '\r':
  626.       /*
  627.        * set the new x position
  628.        */
  629.       ws->x = wc->dx;
  630.       break;
  631.    case '\t':
  632.       xdis(w, "        ", 8 - (XTOCOL(w,ws->x) & 7));
  633.       break;
  634.       /*
  635.        * Handle backspaces.  This implements cooked mode echo handling.
  636.        */
  637.    case '\177':
  638.    case '\010': {
  639.       int i = 0, pre_x;
  640.  
  641.       /*
  642.        * Start with the last character queued up.
  643.        */
  644.       i--;
  645.       /*
  646.        * Trot back to the control-H itself.
  647.        */
  648.       while ((i>-EQUEUELEN) && (EVQUESUB(w,i) != c)) {
  649.      i--;
  650.      }
  651.       if (i == -EQUEUELEN) break;
  652.       /*
  653.        * Go past the control-H.
  654.        */
  655.       i--;
  656.       /*
  657.        * Go back through any number of control-H's from prior lifetimes.
  658.        */
  659.       while((i > -EQUEUELEN) && !isprint(EVQUESUB(w,i))) {
  660.      i--;
  661.      }
  662.       if (i == -EQUEUELEN) break;
  663.  
  664.       /*
  665.        * OK, here's the character we're actually rubbing out.  Back up.
  666.        */
  667.       c = EVQUESUB(w,i);
  668.       pre_x = ws->x;
  669.       ws->x -= TEXTWIDTH(w, &c, 1);
  670.       /*
  671.        * Physically erase the character from the queue.  This results in
  672.        * two control-H's present in the queue.
  673.        */
  674.       *evquesub(w,i) = '\010';
  675.       /*
  676.        * Save the backed-up position, and draw spaces through the erased.
  677.        */
  678.       i = ws->x;
  679.       while(ws->x < pre_x) {
  680.      xdis(w, " ",1);
  681.      }
  682.       ws->x = i;
  683.       break;
  684.       }
  685.     /*
  686.      * bell (control-G)
  687.      */
  688.     case '\007':
  689.       break;
  690.    default:
  691.       xdis(w, &c, 1);
  692.       }
  693.    /*
  694.     * turn the cursor back on
  695.     */
  696.    return 0;
  697.    }
  698.  
  699. /*
  700.  * wgetq - get event from pending queue
  701.  */
  702. int wgetq(wbp w, dptr res)
  703.    {
  704.    MSG m;
  705.    wsp ws;
  706.    int first = 0;
  707.    extern jmp_buf mark_sj;
  708.  
  709.    if (!w || !(ws = w->window) || !(ws->win)) {
  710.       return -1;
  711.       }
  712.    while (1) {
  713.       /*
  714.        * grab the built up queue
  715.        */
  716.       if (!EVQUEEMPTY(ws)) {
  717.      EVQUEGET(ws, *res);
  718.      if (ws->hasCaret) {
  719.             HideCaret(ws->iconwin);
  720.             DestroyCaret();
  721.             ws->hasCaret = 0;
  722.             }
  723.      return 1;
  724.      }
  725.       if (ISCURSORON(w) && !ws->hasCaret && GetActiveWindow() == ws->iconwin) {
  726.          CreateCaret(ws->iconwin, NULL, FWIDTH(w), FHEIGHT(w));
  727.          SetCaretPos(ws->x, ws->y - ASCENT(w));
  728.          SetCaretBlinkTime(500);
  729.          ShowCaret(ws->iconwin);
  730.          ws->hasCaret = 1;
  731.          }
  732.       if (GetMessage(&m, NULL, 0, 0) == 0) longjmp(mark_sj, -1);
  733.       if (TranslateMessage(&m) == 0) {
  734.      DispatchMessage(&m);
  735.      }
  736.       }
  737.    }
  738.  
  739. /*
  740.  * determine the new size of the client
  741.  */
  742. int setheight(w, height)
  743. wbp w;
  744. int height;
  745.    {
  746.    wsp ws = w->window;
  747.    ws->height = height;
  748.    return Succeeded;
  749.    }
  750.  
  751. /*
  752.  * determine new size of client
  753.  */
  754. int setwidth(w, width)
  755. wbp w;
  756. SHORT width;
  757.    {
  758.    wsp ws = w->window;
  759.    ws->width = width;
  760.    return Succeeded;
  761.    }
  762.  
  763. int setgeometry(w, geo)
  764. wbp w;
  765. char *geo;
  766.    {
  767.    wsp ws = w->window;
  768.    int width = 0, height = 0;
  769.    int x = 0, y = 0, status;
  770.    if ((status = parsegeometry(geo, &x, &y, &width, &height)) == 0)
  771.       return Error;
  772.    if (status & 1) {
  773.       ws->width = width;
  774.       ws->height = height;
  775.       }
  776.    if (status & 2) {
  777.       ws->posx = x;
  778.       ws->posy = y;
  779.       }
  780.    return Succeeded;
  781.    }
  782.  
  783. int setcanvas(w,s)
  784. wbp w;
  785. char *s;
  786.    {
  787.    int cmd;
  788.    wsp ws = w->window;
  789.    HWND stdwin = ws->win;
  790.  
  791.    if (!strcmp(s, "iconic")) {
  792.       cmd = SW_MINIMIZE;
  793.       CLRTOBEHIDDEN(ws);
  794.       }
  795.    else if (!strcmp(s, "normal")) {
  796.       cmd = SW_RESTORE;
  797.       CLRTOBEHIDDEN(ws);
  798.       }
  799.    else if (!strcmp(s, "maximal")) {
  800.       cmd = SW_SHOWMAXIMIZED;
  801.       CLRTOBEHIDDEN(ws);
  802.       }
  803.    else if (!strcmp(s, "hidden")) {
  804.       cmd = SW_HIDE;
  805.       SETTOBEHIDDEN(ws);
  806.       }
  807.    else {
  808.       return Error;
  809.       }
  810.    if (stdwin)
  811.       ShowWindow(stdwin, cmd);
  812.  
  813.    return Succeeded;
  814.    }
  815.  
  816. int seticonicstate(w, val)
  817. wbp w;
  818. char *val;
  819.    {
  820.    int height;
  821.    return Failed;
  822.    }
  823.  
  824. int seticonlabel(w, val)
  825. wbp w;
  826. char *val;
  827.    {
  828.    wsp ws = w->window;
  829.    if (ws->iconlabel != NULL) free(ws->iconlabel);
  830.    ws->iconlabel = salloc(val);
  831.    if (ws->win && IsIconic(ws->win))
  832.       SetWindowText(ws->win, ws->iconlabel);
  833.    return Succeeded;
  834.    }
  835.  
  836. int seticonpos(w, val)
  837. wbp w;
  838. char *val;
  839.    {
  840.    return Failed;
  841.    }
  842.  
  843.  
  844. int setwindowlabel(w, val)
  845. wbp w;
  846. char *val;
  847.    {
  848.    wsp ws = w->window;
  849.    /*
  850.     * plug in the new string
  851.     */
  852.    if (ws->windowlabel != NULL)
  853.       free(ws->windowlabel);
  854.    ws->windowlabel = salloc(val);
  855.  
  856.    /*
  857.     * if we have to update, do it
  858.     */
  859.    if (ws->win && !IsIconic(ws->win))
  860.       SetWindowText(ws->win, ws->windowlabel);
  861.    return Succeeded;
  862.    }
  863.  
  864. int setcursor(w, on)
  865. wbp w;
  866. int on;
  867.    {
  868.    wsp ws = w->window;
  869.    if (on) {
  870.       SETCURSORON(w);
  871.       }
  872.    else {
  873.       CLRCURSORON(w);
  874.       }
  875.    return Succeeded;
  876.    }
  877.  
  878. HFONT findfont(wbp w, char *family, int size, int flags)
  879. {
  880.    int weight;
  881.    char slant, spacing;
  882.  
  883.    if (size < 0) size = DEFAULTFONTSIZE;
  884.  
  885.    if (flags & FONTFLAG_MEDIUM)
  886.       weight = FW_MEDIUM;
  887.    else if ((flags & FONTFLAG_DEMI) && (flags & FONTFLAG_BOLD))
  888.       weight = FW_DEMIBOLD;
  889.    else if (flags & FONTFLAG_BOLD)
  890.       weight = FW_BOLD;
  891.    else if (flags & FONTFLAG_DEMI)
  892.       weight = FW_SEMIBOLD;
  893.    else if (flags & FONTFLAG_LIGHT)
  894.       weight = FW_LIGHT;
  895.    else
  896.       weight = FW_DONTCARE;
  897.  
  898.    if (flags & FONTFLAG_ITALIC)
  899.       slant = 1;
  900.    else
  901.       slant = 0;
  902.  
  903.    if (flags & FONTFLAG_PROPORTIONAL)
  904.       spacing = VARIABLE_PITCH;
  905.    else if (flags & FONTFLAG_MONO)
  906.       spacing = FIXED_PITCH;
  907.    else spacing = DEFAULT_PITCH;
  908.  
  909.    return CreateFont(size, 0, 0, 0, weight, slant, 0, 0, DEFAULT_CHARSET,
  910.         OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
  911.         spacing, family);
  912. }
  913.  
  914. /*
  915.  * Set the window's font by name.
  916.  */
  917. int setfont(w, s)
  918. wbp w;
  919. char **s;
  920.    {
  921.    int flags, size;
  922.    wsp ws = w->window;
  923.    wcp wc = w->context;
  924.    HFONT hf;
  925.    TEXTMETRIC    metrics;
  926.    HDC tmpdc;
  927.  
  928.    char family[MAXFONTWORD+1];
  929.    char *stdfam;
  930.  
  931.    if (parsefont(*s, family, &flags, &size)) {
  932.       /*
  933.        * This is a legal Icon font spec.
  934.        * Check first for special "standard" family names.
  935.        */
  936.       if (!strcmp(family, "mono") || !strcmp(family, "fixed")) {
  937.      stdfam = "Lucida Sans";
  938.      flags |= FONTFLAG_MONO + FONTFLAG_SANS;
  939.      }
  940.       else if (!strcmp(family, "typewriter")) {
  941.      stdfam = "courier";
  942.      flags |= FONTFLAG_MONO + FONTFLAG_SERIF;
  943.      }
  944.       else if (!strcmp(family, "sans")) {
  945.      stdfam = "swiss";
  946.      flags |= FONTFLAG_PROPORTIONAL + FONTFLAG_SANS;
  947.      }
  948.       else if (!strcmp(family, "serif")) {
  949.      stdfam = "roman";
  950.      flags |= FONTFLAG_PROPORTIONAL + FONTFLAG_SERIF;
  951.      }
  952.       else stdfam = NULL;
  953.    
  954.       if (stdfam) {
  955.      /*
  956.       * Standard name: first try preferred family, then generalize.
  957.       */
  958.      hf = findfont(w, stdfam, size, flags);
  959.      if (hf == NULL)
  960.         hf = findfont(w, NULL, size, flags);
  961.      }
  962.       else {
  963.      /*
  964.       * Any other name: must match as specified.
  965.       */
  966.      hf = findfont(w, family, size, flags);
  967.      }
  968.    
  969.       if (hf != NULL) {
  970.      if (wc->font->font)
  971.         DeleteObject(wc->font->font);
  972.      wc->font->font = hf;
  973.      free(wc->font->name);
  974.      wc->font->name = salloc(*s);
  975.  
  976.          tmpdc = GetDC(ws->iconwin);
  977.          SelectObject(tmpdc, hf);
  978.          GetTextMetrics(tmpdc, &metrics);
  979.          ReleaseDC(ws->iconwin, tmpdc);
  980.          wc->font->ascent = metrics.tmAscent;
  981.          wc->font->descent = metrics.tmDescent;
  982.          wc->font->charwidth = metrics.tmMaxCharWidth;
  983.          wc->font->height = metrics.tmHeight;
  984.      return Succeeded;
  985.      }
  986.       }
  987.    return Failed;
  988.    }
  989.  
  990. /*
  991.  * rebind() - bind w's context to that of w2.
  992.  */
  993. int rebind(w, w2)
  994. wbp w, w2;
  995.    {
  996.    wsp ws = w->window;
  997.    /* decrement w->context->refcount?  increment w2->context->refcount? */
  998.    w->context = w2->context;
  999.    return Succeeded;
  1000.    }
  1001.  
  1002. novalue setclip(w)
  1003. wbp w;
  1004.    {
  1005.    wcp wc = w->context;
  1006.    if (wc->cliprgn)
  1007.       DeleteObject(wc->cliprgn);
  1008.    if (wc->clipw >= 0)
  1009.       wc->cliprgn = CreateRectRgn(wc->clipx, wc->clipy,
  1010.                   wc->clipx + wc->clipw - 1,
  1011.                   wc->clipy + wc->cliph - 1);
  1012.    else
  1013.       wc->cliprgn = NULL;
  1014.    }
  1015.  
  1016. novalue unsetclip(w)
  1017. wbp w;
  1018.    {
  1019.    wcp wc = w->context;
  1020.    if (wc->cliprgn)
  1021.       DeleteObject(wc->cliprgn);
  1022.    wc->cliprgn = NULL;
  1023.    }
  1024.  
  1025.  int lowerWindow(wbp w)
  1026.    {
  1027.    wsp ws = w->window;
  1028.    if (ws->win)
  1029.       SetWindowPos(ws->win, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
  1030.    return Succeeded;
  1031.    }
  1032.  
  1033. int raiseWindow(wbp w)
  1034.    {
  1035.    wsp ws = w->window;
  1036.    if (ws->win)
  1037.       SetWindowPos(ws->win, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
  1038.    return Succeeded;
  1039.    }
  1040.  
  1041. int nativecolor(w, s, r, g, b)
  1042. wbp w;
  1043. char *s;
  1044. long *r, *g, *b;
  1045.    {
  1046.    return 0;                    /* no new colors beyond those of Icon */
  1047.    }
  1048. /*
  1049.  * convert an Icon linear color into an MS Windows color value
  1050.  */
  1051. SysColor mscolor(wbp w, long r, long g, long b)
  1052. {
  1053.    SysColor x;
  1054.    double invgamma = 1.0 / w->context->gamma;
  1055.    long int red, green, blue;
  1056.  
  1057.    red   = 65535L * pow(r / 65535.0, invgamma);
  1058.    green = 65535L * pow(g / 65535.0, invgamma);
  1059.    blue  = 65535L * pow(b / 65535.0, invgamma);
  1060.    return RGB(red >> 8, green >> 8, blue >> 8);
  1061. }
  1062.  
  1063. /*
  1064.  * Set the context's fill style by name.
  1065.  */
  1066. int setfillstyle(w, s)
  1067. wbp w;
  1068. char *s;
  1069.    {
  1070.    wcp wc = w->context;
  1071.  
  1072.    if (!strcmp(s, "solid")) {
  1073.       wc->brush.lbStyle = wc->fillstyle = BS_SOLID;
  1074.       wc->brush.lbColor = PALCLR(wc->fg);
  1075.       }
  1076.    else {
  1077.       if (!strcmp(s, "masked")
  1078.       || !strcmp(s, "stippled") || !strcmp(s, "patterned")) {
  1079.      wc->brush.lbStyle = wc->fillstyle = BS_PATTERN;
  1080.      wc->brush.lbColor = PALCLR(wc->fg);
  1081.      wc->brush.lbHatch = wc->pattern;
  1082.          wc->bkmode = TRANSPARENT;
  1083.      }
  1084.       else if (!strcmp(s, "textured")
  1085.       || !strcmp(s, "opaquestippled") || !strcmp(s, "opaquepatterned")) {
  1086.      wc->brush.lbStyle = wc->fillstyle = BS_PATTERN;
  1087.      wc->brush.lbColor = PALCLR(wc->fg);
  1088.      wc->brush.lbHatch = wc->pattern;
  1089.      }
  1090.       else {
  1091.      return Error;
  1092.      }
  1093.       }
  1094.    return Succeeded;
  1095.    }
  1096.  
  1097. /*
  1098.  * Set the context's line style by name.
  1099.  */
  1100. int setlinestyle(w, s)
  1101. wbp w;
  1102. char *s;
  1103.    {
  1104.    wcp wc = w->context;
  1105.    SHORT ltype;
  1106.  
  1107.    if ((ltype = si_s2i(siLineTypes, s)) < 0)
  1108.       return Error;
  1109.    wc->pen.lopnStyle = ltype;
  1110.    resetfg(w);
  1111.    if(!strcmp(s, "striped")) wc->bkmode = OPAQUE;
  1112.    else wc->bkmode = TRANSPARENT;
  1113.    return Succeeded;
  1114.    }
  1115.  
  1116. /*
  1117.  * Set the context's line width
  1118.  */
  1119. int setlinewidth(wbp w, LONG linewid)
  1120.    {
  1121.    wcp wc = w->context;
  1122.    wc->pen.lopnWidth.x = wc->pen.lopnWidth.y =
  1123.       wc->bgpen.lopnWidth.x = wc->bgpen.lopnWidth.y = linewid;
  1124.    return Succeeded;
  1125.    }
  1126.  
  1127.  
  1128. /*
  1129.  * Set the foreground to draw in a mutable color
  1130.  */
  1131. int isetfg(wbp w, int i)
  1132.    {
  1133.    char tmp[20];
  1134.    wcp wc = w->context;
  1135.    if (-i > numColors) return Failed;
  1136.    wc->fg = (0x01000000L | -i);
  1137.    sprintf(tmp, "%ld", -i);
  1138.    if (wc->fgname != NULL) free(wc->fgname);
  1139.    wc->fgname = salloc(tmp);
  1140.    wc->pen.lopnColor = wc->fg;
  1141.    wc->brush.lbStyle = BS_SOLID;
  1142.    wc->brush.lbColor = wc->fg;
  1143.    return Succeeded;
  1144.    }
  1145.  
  1146. /*
  1147.  * Set the context's background color by color cell.
  1148.  */
  1149. int isetbg(w, i)
  1150. wbp w;
  1151. int i;
  1152.    {
  1153.    char tmp[20];
  1154.    wcp wc = w->context;
  1155.    if (-i > numColors) return Failed;
  1156.    wc->bg = (0x01000000L | -i);
  1157.    sprintf(tmp, "%ld", -i);
  1158.    if (wc->bgname != NULL) free(wc->bgname);
  1159.    wc->bgname = salloc(tmp);
  1160.    wc->bgpen.lopnColor = wc->bg;
  1161.    wc->bgbrush.lbStyle = BS_SOLID;
  1162.    wc->bgbrush.lbColor = wc->bg;
  1163.    return ISXORREVERSE(w) ? resetfg(w) : Succeeded;
  1164.    }
  1165.  
  1166.  
  1167. int getdepth(wbp w)
  1168. {
  1169.    int i, j, k;
  1170.    STDLOCALS(w);
  1171.    i = GetDeviceCaps(pixdc, BITSPIXEL);
  1172.    j = GetDeviceCaps(pixdc, PLANES);
  1173.    FREE_STDLOCALS(w);
  1174.    return i * j;
  1175. }
  1176.  
  1177. int devicecaps(wbp w, int i)
  1178. {
  1179.    int rv;
  1180.    STDLOCALS(w);
  1181.    rv = GetDeviceCaps(pixdc, i);
  1182.    FREE_STDLOCALS(w);
  1183.    return rv;
  1184. }
  1185.  
  1186. /*
  1187.  * Reset the context's foreground color to whatever it is supposed to be.
  1188.  */
  1189. int resetfg(w)
  1190. wbp w;
  1191.    {
  1192.    return setfg(w, w->context->fgname);
  1193.    }
  1194.  
  1195. int alc_rgb(wbp w, SysColor rgb)
  1196. {
  1197.    int i;
  1198.    wsp ws = w->window;
  1199.    HDC hdc;
  1200.    PALETTEENTRY pe;
  1201.    LOGPALETTE lp;
  1202.    if (palette) {
  1203.       for (i=0; i < numColors; i++) {
  1204.          if (rgb == scp[i].c && scp[i].type == SHARED) break;
  1205.      }
  1206.       if (i == numColors) {
  1207.          numColors++;
  1208.      if (ResizePalette(palette, numColors) == 0) {
  1209.         numColors--;
  1210.         return Failed;
  1211.             }
  1212.          scp = realloc(scp, numColors * sizeof(struct wcolor));
  1213.          if (scp == NULL) { numColors--; return Failed; }
  1214.      scp[numColors - 1].c = rgb;
  1215.      scp[numColors - 1].type = SHARED;
  1216.      sprintf(scp[numColors - 1].name, "%d,%d,%d",
  1217.                  RED(rgb), GREEN(rgb), BLUE(rgb));
  1218.          lp.palNumEntries = 1;
  1219.      lp.palVersion = 0x300;
  1220.      lp.palPalEntry[0].peFlags = 0;
  1221.      lp.palPalEntry[0].peRed = RED(rgb);
  1222.      lp.palPalEntry[0].peGreen = GREEN(rgb);
  1223.      lp.palPalEntry[0].peBlue = BLUE(rgb);
  1224.          SetPaletteEntries(palette, numColors - 1, 1, lp.palPalEntry);
  1225.      hdc = GetDC(ws->iconwin);
  1226.      SelectPalette(hdc, palette, FALSE);
  1227.      RealizePalette(hdc);
  1228.      ReleaseDC(ws->iconwin, hdc);
  1229.      }
  1230.       }
  1231.    return Succeeded;
  1232. }
  1233.  
  1234. /*
  1235.  * Set the context's foreground color
  1236.  */
  1237. int setfg(wbp w, char *val)
  1238.    {
  1239.    long r, g, b;
  1240.    wcp wc = w->context;
  1241.    if (parsecolor(w, val, &r, &g, &b) == Succeeded) {
  1242.       wc->fg = mscolor(w, r, g, b);
  1243.       if (alc_rgb(w, wc->fg) == Failed) return Failed;
  1244.       if (!wc->fgname || strcmp(wc->fgname, val)) {
  1245.          if (wc->fgname)
  1246.             free(wc->fgname);
  1247.          wc->fgname = salloc(val);
  1248.      }
  1249.       wc->brush.lbColor =
  1250.      PALCLR(ISXORREVERSE(w) ? ((wc->fg ^ wc->bg) & 0x00FFFFFF) : wc->fg);
  1251.       wc->pen.lopnColor = wc->brush.lbColor;
  1252.       wc->brush.lbStyle = wc->fillstyle;
  1253.       if (wc->fillstyle == BS_PATTERN)
  1254.      wc->brush.lbHatch = wc->pattern;
  1255.       return Succeeded;
  1256.       }
  1257.    return Failed;
  1258.    }
  1259.  
  1260. /*
  1261.  * Set the window context's background color
  1262.  */
  1263. int setbg(wbp w, char *val)
  1264.    {
  1265.    long r, g, b;
  1266.    wcp wc = w->context;
  1267.    if (parsecolor(w, val, &r, &g, &b) == Succeeded) {
  1268.       wc->bg = mscolor(w, r, g, b);
  1269.       if (alc_rgb(w, wc->bg) == Failed) return Failed;
  1270.       if (wc->bgname != NULL) free(wc->bgname);
  1271.       wc->bgname = salloc(val);
  1272.       wc->bgpen.lopnColor = PALCLR(wc->bg);
  1273.       wc->bgbrush.lbStyle = BS_SOLID;
  1274.       wc->bgbrush.lbColor = PALCLR(wc->bg);
  1275.       return ISXORREVERSE(w) ? resetfg(w) : Succeeded;
  1276.       }
  1277.    return Failed;
  1278.    }
  1279.  
  1280. /*
  1281.  * Set the gamma correction factor.
  1282.  */
  1283. int setgamma(w, gamma)
  1284. wbp w;
  1285. double gamma;
  1286.    {
  1287.    wcp wc = w->context;
  1288.    wc->gamma = gamma;
  1289.    setfg(w, wc->fgname);
  1290.    setbg(w, wc->bgname);
  1291.    return 1;
  1292.    }
  1293.  
  1294. /*
  1295.  * setpointer() - define a mouse pointer shape
  1296.  */
  1297. int setpointer(w, val)
  1298. wbp w;
  1299. char *val;
  1300.    {
  1301.    HCURSOR c;
  1302.  
  1303.    if (!strcmp(val,"arrow")) val = IDC_ARROW;
  1304.    else if (!strcmp(val,"cross")) val = IDC_CROSS;
  1305.    else if (!strcmp(val,"ibeam")) val = IDC_IBEAM;
  1306.    else if (!strcmp(val,"uparrow")) val = IDC_UPARROW;
  1307.    else if (!strcmp(val,"wait")) val = IDC_WAIT;
  1308.    else return Failed;
  1309.  
  1310.    c = LoadCursor(mswinInstance, val);
  1311.    c = SetCursor(c);
  1312.    /* should save old cursor and restore it when it moves outside our window */
  1313.  
  1314.    return Succeeded;
  1315.    }
  1316.  
  1317. /*
  1318.  * setdrawop() - set the drawing operation
  1319.  */
  1320. int setdrawop(w, val)
  1321. wbp w;
  1322. char *val;
  1323.    {
  1324.    wcp wc = w->context;
  1325.    if (!strcmp(val,"reverse")) {
  1326.       if (!ISXORREVERSE(w)) {
  1327.      SETXORREVERSE(w);
  1328.          wc->drawop = R2_XORPEN;
  1329.          resetfg(w);
  1330.      }
  1331.       }
  1332.    else {
  1333.       if (ISXORREVERSE(w)) {
  1334.      CLRXORREVERSE(w);
  1335.          resetfg(w);
  1336.      }
  1337.       wc->drawop = si_s2i(drawops,val);
  1338.       if (wc->drawop == -1) { wc->drawop = R2_COPYPEN; return Error; }
  1339.       }
  1340.    return Succeeded;
  1341.    }
  1342.  
  1343. setdisplay(wbp w, char *val)
  1344.    {
  1345.    return Failed;
  1346.    }
  1347.  
  1348. setimage(wbp w, char *val)
  1349.    {
  1350.    wsp ws = w->window;
  1351.    int status;
  1352.    ws->initialPix = loadimage(w, val, &(ws->width), &(ws->height),
  1353.               0, &status);
  1354.    if (ws->initialPix == (HBITMAP) NULL) return Failed;
  1355.    return Succeeded;
  1356.    }
  1357.  
  1358. setleading(w, i)
  1359. wbp w;
  1360. int i;
  1361.    {
  1362.    wcp wc = w->context;
  1363.    wc->leading = i;
  1364.    }
  1365.  
  1366. novalue toggle_fgbg(w)
  1367. wbp w;
  1368.    {
  1369.    SysColor tmp;
  1370.    LOGPEN tpen;
  1371.    LOGBRUSH tbrush;
  1372.    wcp wc = w->context;
  1373.    tmp = wc->fg;
  1374.    wc->fg = wc->bg;
  1375.    wc->bg = tmp;
  1376.    tpen = wc->pen;
  1377.    wc->pen = wc->bgpen;
  1378.    wc->bgpen = tpen;
  1379.    tbrush = wc->brush;
  1380.    wc->brush = wc->bgbrush;
  1381.    wc->bgbrush = tbrush;
  1382.    }
  1383.  
  1384. int getvisual(w, answer)
  1385. wbp w;
  1386. char *answer;
  1387.    {
  1388.    return Failed;
  1389.    }
  1390.  
  1391. /*
  1392.  * getpos() - update the window state's notion of its current position
  1393.  */
  1394. int getpos(w)
  1395. wbp w;
  1396.    {
  1397.    return Succeeded;
  1398.    }
  1399.  
  1400. novalue getfg(w, answer)
  1401. wbp w;
  1402. char *answer;
  1403.    {
  1404.    strcpy(answer, w->context->fgname);
  1405.    }
  1406.  
  1407. novalue getbg(w, answer)
  1408. wbp w;
  1409. char *answer;
  1410.    {
  1411.    strcpy(answer, w->context->bgname);
  1412.    }
  1413.  
  1414. novalue getlinestyle(w, answer)
  1415. wbp w;
  1416. char *answer;
  1417.    {
  1418.    wcp wc = w->context;
  1419.    char *ptr = si_i2s(siLineTypes, wc->pen.lopnStyle);
  1420.    if (ptr != NULL)
  1421.       strcpy(answer, ptr);
  1422.    else
  1423.       strcpy(answer, "solid");
  1424.    }
  1425.  
  1426. novalue getfntnam(w, answer)
  1427. wbp w;
  1428. char *answer;
  1429.    {
  1430.    strcpy(answer, w->context->font->name);
  1431.    }
  1432.  
  1433. novalue getpointername(w, answer)
  1434. wbp w;
  1435. char *answer;
  1436.    {
  1437.    char *s;
  1438.    wsp ws = w->window;
  1439.    strcpy(answer, "???");
  1440.    }
  1441.  
  1442. novalue getdisplay(wbp w, char *answer)
  1443.    {
  1444.    strcpy(answer, "local");
  1445.    }
  1446.  
  1447. novalue getdrawop(w, answer)
  1448. wbp w;
  1449. char *answer;
  1450.    {
  1451.    char *s;
  1452.    if (ISXORREVERSE(w)) s = "reverse";
  1453.    else s = si_i2s(drawops, w->context->drawop);
  1454.    if (s) sprintf(answer, "%s", s);
  1455.    else strcpy(answer, "copy");
  1456.    }
  1457.  
  1458. novalue geticonic(w, answer)
  1459. wbp w;
  1460. char *answer;
  1461.    {
  1462.    getcanvas(w, answer);
  1463.    }
  1464.  
  1465. novalue getcanvas(w, answer)
  1466. wbp w;
  1467. char *answer;
  1468.    {
  1469.    wsp ws = w->window;
  1470.    if (ws->iconwin) {
  1471.       if (!IsWindowVisible(ws->iconwin)) sprintf(answer, "hidden");
  1472.       else if (IsIconic(ws->iconwin)) sprintf(answer, "iconic");
  1473.       else if (IsZoomed(ws->iconwin)) sprintf(answer, "maximal");
  1474.       else sprintf(answer,"normal");
  1475.       }
  1476.    else sprintf(answer,"hidden");
  1477.    }
  1478.  
  1479. int geticonpos(w, val)
  1480. wbp w;
  1481. char *val;
  1482.    {
  1483.    return Failed;
  1484.    }
  1485.  
  1486. /*
  1487.  * erase an area
  1488.  */
  1489. novalue eraseArea(w,x,y,width,height)
  1490. wbp w;
  1491. int x, y, width, height;
  1492.    {
  1493.    HBRUSH hb, oldbrush, oldbrush2;
  1494.    XRectangle rect;
  1495.    STDLOCALS(w);
  1496.    hb = CreateBrushIndirect(&(wc->bgbrush));
  1497.    if (stdwin) oldbrush = SelectObject(stddc, hb);
  1498.    oldbrush2 = SelectObject(pixdc, hb);
  1499.    rect.left = x; rect.right = x + width;
  1500.    rect.top = y; rect.bottom = y + height;
  1501.  
  1502.    if (stdwin) FillRect(stddc, &rect, hb);
  1503.    FillRect(pixdc, &rect, hb);
  1504.    DeleteObject(hb);
  1505.    FREE_STDLOCALS(w);
  1506.    }
  1507.  
  1508. /*
  1509.  * copy an area
  1510.  */
  1511. int copyArea(w,w2,x,y,width,height,x2,y2)
  1512. wbp w, w2;
  1513. int x, y, width, height, x2, y2;
  1514.    {
  1515.    RECT r;
  1516.    HDC srcdc, srcpixdc;
  1517.    HBRUSH hb;
  1518.    wsp ws1 = w->window;
  1519.    STDLOCALS(w2);
  1520.    /*
  1521.     * setup device contexts for area copy
  1522.     */
  1523.    SetROP2(pixdc, R2_COPYPEN);
  1524.    hb = CreateBrushIndirect(&(wc->bgbrush));
  1525.    if (stdwin)
  1526.       SetROP2(stddc, R2_COPYPEN);
  1527.    if (w2->window == w->window) {
  1528.       srcdc = pixdc;
  1529.       srcpixdc = pixdc;
  1530.       }
  1531.    else {
  1532.       srcdc = GetDC(w->window->iconwin);
  1533.       srcpixdc = CreateCompatibleDC(srcdc);
  1534.       SetROP2(srcpixdc, R2_COPYPEN);
  1535.       }
  1536.    SelectObject(srcpixdc, w->window->pix);
  1537.  
  1538.    /*
  1539.     * copy area, write unavailable areas with bg color
  1540.     */
  1541.    if (x + width < 0 || y + height < 0 || x >= ws1->pixwidth || y >= ws1->pixheight) {
  1542.       /* source is entirely offscreen, just fill with background */
  1543.       r.left = x2; r.top = y2; r.right = x2 + width; r.bottom = y2 + height;
  1544.       if (stdwin)
  1545.          FillRect(stddc, &r, hb);
  1546.       FillRect(pixdc, &r, hb);
  1547.       }
  1548.    else {
  1549.       if (x < 0) { /* fill pixels to left of source canvas with source bg */
  1550.          r.left = x2; r.top = y2; r.right = x2 -x; r.bottom = y2 + height;
  1551.          if (stdwin)
  1552.             FillRect(stddc, &r, hb);
  1553.          FillRect(pixdc, &r, hb);
  1554.          x = 0;
  1555.          }
  1556.       if (x + width > ws1->pixwidth) { /* fill pixels to right of source */
  1557.          r.left = x2 + ws1->pixwidth - x; r.top = y2;
  1558.          r.right = x2 + width ; r.bottom = y2 + height;
  1559.          if (stdwin)
  1560.             FillRect(stddc, &r, hb);
  1561.          FillRect(pixdc, &r, hb);
  1562.          width = ws1->pixwidth - x;
  1563.          }
  1564.       if (y < 0) { /* fill pixels above source canvas with source bg */
  1565.          r.left = x2; r.top = y2; r.right = x2 + width; r.bottom = y2 - y;
  1566.          if (stdwin)
  1567.             FillRect(stddc, &r, hb);
  1568.          FillRect(pixdc, &r, hb);
  1569.          y = 0;
  1570.          }
  1571.       if (y + height > ws1->pixheight) { /* fill pixels below source */
  1572.          r.left = x2; r.top = y2 + ws1->pixheight - y;
  1573.          r.right = x2 + width; r.bottom = y2 + height;
  1574.          if (stdwin)
  1575.             FillRect(stddc, &r, hb);
  1576.          FillRect(pixdc, &r, hb);
  1577.          height = ws1->pixheight - y;
  1578.          }
  1579.       }
  1580.  
  1581.    if (stdwin)
  1582.       BitBlt(stddc, x2, y2, width, height, srcpixdc, x, y, SRCCOPY);
  1583.    BitBlt(pixdc, x2, y2, width, height, srcpixdc, x, y, SRCCOPY);
  1584.  
  1585.    /*
  1586.     * free resources
  1587.     */
  1588.    if (w2->window != w->window) {
  1589.       ReleaseDC(w->window->iconwin, srcdc);
  1590.       DeleteDC(srcpixdc);
  1591.       }
  1592.    DeleteObject(hb);
  1593.    FREE_STDLOCALS(w2);
  1594.    return Succeeded;
  1595.    }
  1596.  
  1597. int getdefault(w, prog, opt, answer)
  1598. wbp w;
  1599. char *prog, *opt, *answer;
  1600.    {
  1601.    return Failed;
  1602.    }
  1603.  
  1604. /*
  1605.  * Draw a bilevel image.
  1606.  */
  1607. int blimage(w, x, y, width, height, ch, s, len)
  1608. wbp w;
  1609. int x, y, width, height, ch;
  1610. unsigned char *s;
  1611. word len;
  1612.    {
  1613.    unsigned int m, msk1, c, ix, iy;
  1614.    long fg, bg;
  1615.    STDLOCALS(w);
  1616.    /*
  1617.     * Read the image string and set the pixel values.  Note that
  1618.     * the hex digits in sequence fill the rows *right to left*.
  1619.     */
  1620.    m = width % 4;
  1621.    if (m == 0)
  1622.       msk1 = 8;
  1623.    else
  1624.       msk1 = 1 << (m - 1);              /* mask for first byte of row */
  1625.  
  1626.    fg = wc->fg;
  1627.    bg = wc->bg;
  1628.    ix = width;
  1629.    iy = 0;
  1630.    m = msk1;
  1631.    while (len--) {
  1632.       if (isxdigit(c = *s++)) {         /* if hexadecimal character */
  1633.      if (!isdigit(c))               /* fix bottom 4 bits if necessary */
  1634.         c += 9;
  1635.      while (m > 0) {                /* set (usually) 4 pixel values */
  1636.         --ix;
  1637.         if (c & m) {
  1638.            SetPixel(pixdc, ix, iy, PALCLR(wc->fg));
  1639.            }
  1640.         else if (ch != TCH1) {      /* if zeroes aren't transparent */
  1641.            SetPixel(pixdc, ix, iy, PALCLR(wc->bg));
  1642.            }
  1643.         m >>= 1;
  1644.         }
  1645.      if (ix == 0) {                 /* if end of row */
  1646.         ix = width;
  1647.         iy++;
  1648.         m = msk1;
  1649.         }
  1650.      else
  1651.         m = 8;
  1652.      }
  1653.       }
  1654.    if (ix > 0)                          /* pad final row if incomplete */
  1655.       while (ix < width)
  1656.      SetPixel(pixdc, ix++, iy, PALCLR(wc->bg));
  1657.  
  1658.    /*
  1659.     * Put it on the screen.
  1660.     */
  1661.    if (ws->win)
  1662.       BitBlt(stddc, x, y, width, height, pixdc, x, y, SRCCOPY);
  1663.    FREE_STDLOCALS(w);
  1664.    return Succeeded;
  1665.    }
  1666.  
  1667. /*
  1668.  * Draw a character-per-pixel image.
  1669.  */
  1670. int strimage(w, x, y, width, height, e, s, len, on_icon)
  1671. wbp w;
  1672. int x, y, width, height;
  1673. struct palentry *e;
  1674. unsigned char *s;
  1675. word len;
  1676. int on_icon;
  1677.    {
  1678.    register int c;
  1679.    register unsigned int ix;
  1680.    unsigned int iy, tmpw;
  1681.    SysColor clrlist[256];
  1682.    char tmp[24];
  1683.    STDLOCALS(w);
  1684.  
  1685.    if (on_icon) {
  1686.       FREE_STDLOCALS(w);
  1687.       return -1;
  1688.       }
  1689.    /*
  1690.     * Build an array of colors we need
  1691.     */
  1692.    for (c = 0; c < 256; c++)
  1693.       if (e[c].used && e[c].valid) {
  1694.      clrlist[c] = mscolor(w, e[c].clr.red, e[c].clr.green, e[c].clr.blue);
  1695.      }
  1696.  
  1697.    /*
  1698.     * Read the image string and set the pixel values.
  1699.     */
  1700.    ix = x;
  1701.    iy = y;
  1702.    tmpw = x + width;
  1703.    while (len--) {
  1704.       c = *s++;
  1705.       if (e[c].valid) {                         /* put char if valid */
  1706.      SetPixel(pixdc, ix, iy, clrlist[c]);
  1707.      if (++ix >= tmpw) {                    /* advance */
  1708.         ix = x;                             /* reset for new row */
  1709.         iy++;
  1710. #if 0
  1711.       if (iy & 7 == 0) {
  1712.      pollevent();
  1713.      }
  1714. #endif
  1715.         }
  1716.      }
  1717.       else if (c == TCH1 || c == TCH2) {        /* advance if transparent */
  1718.      if (++ix >= tmpw) {
  1719.         ix = x;                             /* reset for new row */
  1720.         iy++;
  1721. #if 0
  1722.       if (iy & 7 == 0) {
  1723.      pollevent();
  1724.      }
  1725. #endif
  1726.         }
  1727.      }
  1728.       }
  1729.    if (ix > 0)                          /* pad final row if incomplete */
  1730.       while (ix < width)
  1731.      SetPixel(pixdc, x+ix++, y+iy, PALCLR(wc->bg));
  1732.  
  1733.    /*
  1734.     * Put it on the screen.
  1735.     */
  1736.    if (on_icon) {
  1737.       FREE_STDLOCALS(w);
  1738.       return -1;
  1739.       }
  1740.    else {
  1741.       if (ws->win)
  1742.      BitBlt(stddc, x, y, width, height, pixdc, x, y, SRCCOPY);
  1743.       }
  1744.    FREE_STDLOCALS(w);
  1745.    return 0;
  1746.    }
  1747.  
  1748.  
  1749.  
  1750. /*
  1751.  * imqsearch(key,base,nel) - binary search hardwired for images
  1752.  *
  1753.  *  A binary search routine with arguments similar to qsort(3).
  1754.  *  Returns a pointer to the item matching "key", or NULL if none.
  1755.  *  This is called a LOT, so it is hardwired for speed.
  1756.  *  Based on Bentley, CACM 28,7 (July, 1985), p. 676.
  1757.  */
  1758.  
  1759. SysColor * imqsearch (SysColor key, SysColor *base, int nel)
  1760. {
  1761.    int l, u, m;
  1762.    SysColor * a;
  1763.  
  1764.    l = 0;
  1765.    u = nel - 1;
  1766.    while (l <= u) {
  1767.       m = (l + u) / 2;
  1768.       a = base + m;
  1769.       if (*a < key)
  1770.          l = m + 1;
  1771.       else if (*a > key)
  1772.          u = m - 1;
  1773.       else
  1774.          return a;
  1775.       }
  1776.    while (a>base && key < *a) a--;
  1777.    while (a<base+nel && key > *a) a++;
  1778.    return a;
  1779. }
  1780.  
  1781. /*
  1782.  * getimstr -- get an image as a string.
  1783.  *
  1784.  * Stores the specified subimage in data, one pixel per byte, and sets
  1785.  * entries in paltbl corresponding to the pixel values that were used.
  1786.  */
  1787. int getimstr(w, xx, yy, width, height, paltbl, data)
  1788. wbp w;
  1789. int xx, yy, width, height;
  1790. struct palentry paltbl[DMAXCOLORS];
  1791. unsigned char *data;
  1792.    {
  1793.    SysColor px, lastpx, clist[DMAXCOLORS], *lp;
  1794.    int i, ncolors, x, y, wd = xx + width, ht = yy + height;
  1795.    STDLOCALS(w);
  1796.  
  1797.    /*
  1798.     * Make a sorted list of the pixel values of the colors that are in
  1799.     * use.  Search this list for every pixel and store the resulting
  1800.     * list index as the color index.
  1801.     */
  1802.    ncolors = 1;
  1803.    clist[0] = lastpx = GetPixel(pixdc, xx, yy);
  1804.    for (y = yy; y < ht; y++) {
  1805. #if 0
  1806.       /* want to do pollevent here, but can't inside a STDLOCALS declaration */
  1807.       if (y & 1) { /* how often to process window events? */
  1808.      pollevent();
  1809.      }
  1810. #endif
  1811.       for (x = xx; x < wd; x++) {
  1812.      px = GetPixel(pixdc, x, y);
  1813.      if (px != lastpx) {
  1814.         lastpx = px;
  1815.         lp = imqsearch(px, clist, ncolors);
  1816.         if (*lp != px) {
  1817.            i = ncolors++;
  1818.            while (clist + i != lp) {
  1819.           clist[i] = clist[i-1];
  1820.           i--;
  1821.           }
  1822.            clist[i] = px;
  1823.            }
  1824.         }
  1825.      }
  1826.       }
  1827.  
  1828.    lastpx = GetPixel(pixdc, xx, yy) + 1;
  1829.    for (y = yy; y < height; y++) {
  1830. #if 0
  1831.       /* want to do pollevent here, but can't inside a STDLOCALS declaration */
  1832.       if (y & 1 == 0) {
  1833.      pollevent();
  1834.      }
  1835. #endif
  1836.       for (x = xx; x < width; x++) {
  1837.      px = GetPixel(pixdc, x, y);
  1838.      if (px != lastpx) {
  1839.         lastpx = px;
  1840.         lp = imqsearch(px, clist, ncolors);
  1841.         if (*lp == px)
  1842.            i = lp - clist;
  1843.         else {
  1844.            FREE_STDLOCALS(w);
  1845.            return 0;
  1846.            }
  1847.         }
  1848.      *data++ = i;
  1849.      if (!paltbl[i].used) {
  1850.         paltbl[i].used = 1;
  1851.         paltbl[i].clr.red = RED(px) * 257;
  1852.         paltbl[i].clr.green = GREEN(px) * 257;
  1853.         paltbl[i].clr.blue = BLUE(px) * 257;
  1854.         paltbl[i].valid = 1;
  1855.         }
  1856.      }
  1857.       }
  1858.  
  1859.    FREE_STDLOCALS(w);
  1860.    return 1;
  1861.    }
  1862.  
  1863. int readimage(w, filename, x, y, status)
  1864. wbp w;
  1865. char *filename;
  1866. int x, y, *status;
  1867.    {
  1868.    HBITMAP p;
  1869.    unsigned int width, height;
  1870.    HDC srcdc, srcpixdc;
  1871.  
  1872.    if (!x && !y)
  1873.       p = loadimage(w, filename, &width, &height, 1, status);
  1874.    else
  1875.       p = loadimage(w, filename, &width, &height, 0, status);
  1876.  
  1877.    if (p == (HBITMAP) NULL) {
  1878.      return Failed;
  1879.      }
  1880.  
  1881.    {
  1882.    STDLOCALS(w);
  1883.  
  1884.    srcdc = GetDC(ws->iconwin);
  1885.    srcpixdc = CreateCompatibleDC(srcdc);
  1886.    SelectObject(srcpixdc, p);
  1887.    BitBlt(pixdc, x, y, width, height, srcpixdc, 0, 0, SRCCOPY);
  1888.    if (stdwin)
  1889.       BitBlt(stddc, x, y, width, height, srcpixdc, 0, 0, SRCCOPY);
  1890.    ReleaseDC(ws->iconwin, srcdc);
  1891.    DeleteDC(srcpixdc);
  1892.  
  1893.    /*
  1894.     * Make sure previous ops on p are complete, then free it.
  1895.     */
  1896.    DeleteObject(p);
  1897.    FREE_STDLOCALS(w);
  1898.    return Succeeded;
  1899.    }
  1900.    }
  1901.  
  1902.  
  1903. COLORREF *crp;
  1904. long crpx, crpy, crpw, crph;
  1905.  
  1906. /*
  1907.  * Initialize client for producing pixels from a window, or in this case,
  1908.  * only create a device context once, not once per getpixel.
  1909.  */
  1910. int getpixel_init(w, x, y, width, height)
  1911. wbp w;
  1912. int x, y, width, height;
  1913.    {
  1914.    COLORREF *p;
  1915.    wsp ws = w->window;
  1916.    int i, j, x2, y2;
  1917.    HDC stddc = GetDC(ws->iconwin), pixdc = CreateCompatibleDC(stddc);
  1918.  
  1919.    if (palette) SelectPalette(pixdc, palette, FALSE);
  1920.    SelectObject(pixdc, ws->pix);
  1921.  
  1922.    if (crp) free(crp);
  1923.    /* this looks like a bug for Win16 for images > 100x100 or so... */
  1924.    crp = malloc( width * height * sizeof(COLORREF));
  1925.    p = crp;
  1926.    crpx = x;
  1927.    crpy = y;
  1928.    crpw = width;
  1929.    crph = height;
  1930.    x2 = x + width;
  1931.    y2 = y + height;
  1932.    for(i=y;i<y2;i++)
  1933.       for(j=x;j<x2;j++) {
  1934.          if ((*p++ = GetPixel(pixdc, j, i)) == (COLORREF)-1L) {
  1935.             FREE_STDLOCALS(w);
  1936.             return Failed;
  1937.             }
  1938.          }
  1939.    FREE_STDLOCALS(w);
  1940.    return Succeeded;
  1941.    }
  1942.  
  1943. /*
  1944.  * Return pixel (x,y) from a window
  1945.  */
  1946. int getpixel(wbp w, int x, int y, long *rv, char *s)
  1947.    {
  1948.    COLORREF cr = crp[(y-crpy) * crpw + (x-crpx)];
  1949.    *rv = 1;
  1950.    sprintf(s, "%ld,%ld,%ld",
  1951.        (long)RED(cr)*257L, (long)GREEN(cr)*257L, (long)BLUE(cr)*257L);
  1952.    return Succeeded;
  1953.    }
  1954.  
  1955. int query_pointer(w, pp)
  1956. wbp w;
  1957. XPoint *pp;
  1958.    {
  1959.    wsp ws = w->window;
  1960.    RECT r;
  1961.    if (ws->win) {
  1962.       GetCursorPos(pp);
  1963.       GetWindowRect(ws->win, &r);
  1964.       pp->x -= r.left;
  1965.       pp->y -= r.top;
  1966.       return Succeeded;
  1967.       }
  1968.    return Failed;
  1969.    }
  1970.  
  1971. int query_rootpointer(pp)
  1972. XPoint *pp;
  1973.    {
  1974.    GetCursorPos(pp);
  1975.    return Succeeded;
  1976.    }
  1977.  
  1978. int seticonimage(w, dp)
  1979. wbp w;
  1980. dptr dp;
  1981.    {
  1982.    wsp ws = w->window;
  1983.    return Succeeded;
  1984.    }
  1985.  
  1986. /*
  1987.  * dumpimage -- write an image to a disk file.  Return 0 on failure.
  1988.  */
  1989. int dumpimage(wbp w, char *filename, unsigned int x, unsigned int y,
  1990.           unsigned int width, unsigned int height)
  1991.    {
  1992.    int result = 0;
  1993.    FILE *fp;
  1994.    HDIB dib;
  1995.    HDC  destdc;
  1996.    HBITMAP dumppix;
  1997.    STDLOCALS(w);
  1998.  
  1999.    if (strcmp(".bmp", filename + strlen(filename) - 4) &&
  2000.        strcmp(".BMP", filename + strlen(filename) - 4)) {
  2001.       FREE_STDLOCALS(w);
  2002.       return NoCvt;
  2003.       }
  2004.  
  2005.    /*
  2006.     * extract the desired rectangle from the source bitmap
  2007.     */
  2008.    if (x || y || width != ws->pixwidth || height != ws->pixheight) {
  2009.       dumppix  = CreateCompatibleBitmap(stddc, width, height);
  2010.       destdc   = CreateCompatibleDC(stddc);
  2011.       SelectObject(destdc, dumppix);
  2012.       BitBlt(destdc, 0, 0, width, height, pixdc, x, y, SRCCOPY);   
  2013.       }
  2014.    else dumppix = ws->pix;
  2015.    dib = BitmapToDIB(dumppix, NULL);
  2016.    if (dumppix != ws->pix) {
  2017.       DeleteDC(destdc);
  2018.       DeleteObject(dumppix);
  2019.       }
  2020.  
  2021.    if (dib == NULL) result = Failed;
  2022.    else {
  2023.       if (result = SaveDIB(dib, filename)) { /* != 0 implies error */
  2024.      result = Failed;
  2025.      }
  2026.       else result = Succeeded;
  2027.       DestroyDIB(dib);
  2028.       }
  2029.  
  2030.    FREE_STDLOCALS(w);
  2031.    return result;
  2032.    }
  2033.  
  2034.  
  2035. /*
  2036.  * loadimage
  2037.  */
  2038. HBITMAP loadimage(wbp w, char *filename, unsigned int *width,
  2039.           unsigned int *height, int atorigin, int *status)
  2040.    {
  2041.    HDIB dib;
  2042.    HBITMAP bm;
  2043.    dib = LoadDIB(filename);
  2044.    if (dib != NULL) {
  2045.       LPSTR pdib;
  2046.       bm = DIBToBitmap(dib, 0);
  2047.       pdib = GlobalLock(dib);
  2048.       *width = DIBWidth(pdib);
  2049.       *height = DIBHeight(pdib);
  2050.       GlobalUnlock(dib);
  2051.       DestroyDIB(dib);
  2052.       *status = 0;
  2053.       return bm;
  2054.       }
  2055.    return NULL;
  2056.    }
  2057.  
  2058.  
  2059. char *get_mutable_name(wbp w, int mute_index)
  2060.    {
  2061.    char *tmp;
  2062.    PALETTEENTRY pe;
  2063.    
  2064.    if (-mute_index > numColors || scp[-mute_index].type != MUTABLE) {
  2065.       return NULL;
  2066.       }
  2067.  
  2068.    if (GetPaletteEntries(palette, -mute_index, 1, &pe) == 0) {
  2069.       return NULL;
  2070.       }
  2071.    tmp = scp[-mute_index].name;
  2072.    sprintf(tmp, "%d", mute_index);
  2073.    sprintf(tmp + strlen(tmp) + 1, "%d,%d,%d",
  2074.       (pe.peRed << 8) | 0xff, (pe.peGreen << 8) | 0xff, (pe.peBlue << 8) | 0xff);
  2075.    return tmp + strlen(tmp) + 1;
  2076.    }
  2077.  
  2078. int set_mutable(wbp w, int i, char *s)
  2079.    {
  2080.    long r, g, b;
  2081.    UINT rv;
  2082.    PALETTEENTRY pe;
  2083.    if (palette == 0) return Failed;
  2084.  
  2085.    {
  2086.    STDLOCALS(w);
  2087.    if (parsecolor(w, s, &r, &g, &b) != Succeeded) {
  2088.       FREE_STDLOCALS(w);
  2089.       return Failed;                        /* invalid color specification */
  2090.       }
  2091.    pe.peRed = r >> 8;
  2092.    pe.peGreen = g >> 8;
  2093.    pe.peBlue = b >> 8;
  2094.    pe.peFlags = PC_RESERVED;
  2095.    raiseWindow(w);    /* mutable won't mutate if window isn't active */
  2096. #if 1
  2097.    AnimatePalette(palette, -i, 1, &pe);
  2098.    rv = SetPaletteEntries(palette, -i, 1, &pe);
  2099. #endif
  2100.    UnrealizeObject(palette);
  2101.    RealizePalette(stddc);
  2102.    AnimatePalette(palette, -i, 1, &pe);
  2103.    FREE_STDLOCALS(w);
  2104. }
  2105.    return Succeeded;
  2106.    }
  2107.  
  2108. novalue free_mutable(wbp w, int mute_index)
  2109.    {
  2110.    }
  2111.  
  2112. /*
  2113.  * Allocate a mutable color
  2114.  */
  2115. int mutable_color(wbp w, dptr argv, int argc, int *retval)
  2116.    {
  2117.    long r, g, b;
  2118.    tended char *str;
  2119.    LOGPALETTE lp;
  2120.    {
  2121.    STDLOCALS(w);
  2122.  
  2123.    if (!stddc || ((GetDeviceCaps(stddc, RASTERCAPS) & RC_PALETTE) == 0)) {
  2124.       FREE_STDLOCALS(w);
  2125.       return Failed;
  2126.       }
  2127.  
  2128.    numColors++;
  2129.    scp = realloc(scp, numColors * sizeof(struct wcolor));
  2130.    if (scp == NULL) {
  2131.       FREE_STDLOCALS(w);
  2132.       return Failed;
  2133.       }
  2134.    scp[numColors-1].c = -(numColors-1);
  2135.    sprintf(scp[numColors-1].name, "%d:", -(numColors-1));
  2136.    scp[numColors-1].type = MUTABLE;
  2137.    if (ResizePalette(palette, numColors) == 0) {
  2138.       FREE_STDLOCALS(w);
  2139.       return Failed;
  2140.       }
  2141.  
  2142.    if (argc > 0) {                     /* set the color */
  2143.       if (argc != 1) {
  2144.          FREE_STDLOCALS(w);
  2145.          return Error;
  2146.          }
  2147.       /*
  2148.        * old-style check for C integer
  2149.        */
  2150.       else if (argv[0].dword == D_Integer) {/* check for color cell */
  2151.      if (IntVal(argv[0]) >= 0) {
  2152.             FREE_STDLOCALS(w);
  2153.         return Failed;        /* must be negative */
  2154.             }
  2155.      if (GetPaletteEntries(palette, -IntVal(argv[0]),
  2156.         1, lp.palPalEntry) == 0) {
  2157.             FREE_STDLOCALS(w);
  2158.             return Error;
  2159.             }
  2160.      /* convert to linear color? */
  2161.      }
  2162.       else {
  2163.      if (!cnv:C_string(argv[0],str)) {
  2164.             FREE_STDLOCALS(w);
  2165.         ReturnErrVal(103,argv[0], Error);
  2166.         }
  2167.      if (parsecolor(w, str, &r, &g, &b) != Succeeded) {
  2168.         /* reduce logical palette size and count */
  2169.             FREE_STDLOCALS(w);
  2170.         numColors--;
  2171.             ResizePalette(palette, numColors);
  2172.         return Failed;                   /* invalid color specification */
  2173.         }
  2174.      lp.palPalEntry[0].peRed = r >> 8;
  2175.      lp.palPalEntry[0].peGreen = g >> 8;
  2176.      lp.palPalEntry[0].peBlue = b >> 8;
  2177.      }
  2178.       lp.palNumEntries = 1;
  2179.       lp.palVersion = 0x300;
  2180.       lp.palPalEntry[0].peFlags = PC_RESERVED;
  2181.       SetPaletteEntries(palette, numColors - 1, 1, lp.palPalEntry);
  2182.       UnrealizeObject(palette);
  2183.       RealizePalette(stddc);
  2184.       }
  2185.  
  2186.    *retval = -(numColors - 1);
  2187.    FREE_STDLOCALS(w);
  2188.    return Succeeded;
  2189.    }
  2190.    }
  2191.  
  2192. novalue freecolor(wbp w, char *s)
  2193.    {
  2194.    }
  2195.  
  2196. /*
  2197.  * drawarcs() - assumes x and y are already fixed up for the bitmap
  2198.  */
  2199. void drawarcs(wbp wb, XArc *arcs, int narcs)
  2200.    {
  2201.    register XArc *arc = arcs;
  2202.    int i, halfwidth, halfheight, x1, y1, x2, y2, right, bottom;
  2203.    double a1_a2;
  2204.    HPEN hp, oldpen, oldpen2;
  2205.    STDLOCALS(wb);
  2206.    hp = CreatePenIndirect(&(wc->pen));
  2207.    if (stdwin) oldpen = SelectObject(stddc, hp);
  2208.    oldpen2 = SelectObject(pixdc, hp);
  2209.    for (i = 0; i < narcs; i++, arc++) {
  2210.       halfwidth = arc->width >> 1;
  2211.       halfheight = arc->height >> 1;
  2212.       arc->angle1 = -arc->angle1 - arc->angle2;
  2213.       a1_a2 = arc->angle1 + arc->angle2;
  2214.       x1 = arc->x + halfwidth + (int)(halfwidth * cos(arc->angle1));
  2215.       y1 = arc->y + halfheight - (int)(halfheight * sin(arc->angle1));
  2216.       x2 = arc->x + halfwidth + (int)(halfwidth * cos(a1_a2));
  2217.       y2 = arc->y + halfheight - (int)(halfheight * sin(a1_a2));
  2218.       right = arc->x + arc->width;
  2219.       bottom = arc->y + arc->height;
  2220.       if (ws->win)
  2221.      Arc(stddc, arc->x, arc->y, right, bottom, x1, y1, x2, y2);
  2222.       Arc(pixdc, arc->x, arc->y, right, bottom, x1, y1, x2, y2);
  2223.       }
  2224.    if (stdwin) SelectObject(stddc, oldpen);
  2225.    SelectObject(pixdc, oldpen2);
  2226.    DeleteObject(hp);
  2227.    FREE_STDLOCALS(wb);
  2228.    return;
  2229.    }
  2230.  
  2231.  
  2232. /*
  2233.  * drawlines - Support routine for DrawLine
  2234.  */
  2235. void drawlines(wbinding *wb, XPoint *points, int npoints)
  2236.    {
  2237.    int i, diff, bheight;
  2238.    HPEN hp, oldpen, oldpen2;
  2239.    STDLOCALS(wb);
  2240.    hp = CreatePenIndirect(&(wc->pen));
  2241.    if (stdwin) oldpen = SelectObject(stddc, hp);
  2242.    oldpen2 = SelectObject(pixdc, hp);
  2243.    if (ws->win) {
  2244.       SetBkMode(stddc, wc->bkmode);
  2245.       Polyline(stddc, points, npoints);
  2246.       }
  2247.    SetBkMode(pixdc, wc->bkmode);
  2248.    Polyline(pixdc, points, npoints);
  2249.    if (stdwin) SelectObject(stddc, oldpen);
  2250.    SelectObject(pixdc, oldpen2);
  2251.    DeleteObject(hp);
  2252.    FREE_STDLOCALS(wb);
  2253.    return;
  2254.    }
  2255.  
  2256.  
  2257. /*
  2258.  * drawpoints() - 
  2259.  *  Parameters - the window binding for output, an array of points (assumed
  2260.  *               to be fixed up for bitmap) and the number of points
  2261.  */
  2262. void drawpoints(wbinding *wb, XPoint *points, int npoints)
  2263.    {
  2264.    int i, diff, bheight;
  2265.    XPoint *p;
  2266.    STDLOCALS(wb);
  2267.    if (stdwin) {
  2268.       for(i = 0, p = points; i < npoints; i++, p++) {
  2269.          SetPixel(stddc, p->x, p->y, PALCLR(wc->fg));
  2270.          SetPixel(pixdc, p->x, p->y, PALCLR(wc->fg));
  2271.          }
  2272.       }
  2273.    else {
  2274.       for(i = 0, p = points; i < npoints; i++, p++) {
  2275.          SetPixel(pixdc, p->x, p->y, PALCLR(wc->fg));
  2276.          }
  2277.       }
  2278.    FREE_STDLOCALS(wb);
  2279.    return;
  2280.    }
  2281.  
  2282.  
  2283. /*
  2284.  * drawsegments() -
  2285.  */
  2286. void drawsegments(wbinding *wb, XSegment *segs, int nsegs)
  2287.    {
  2288.    int i, diff, bheight;
  2289.    XPoint ps[2];
  2290.    HPEN hp, oldpen, oldpen2;
  2291.    STDLOCALS(wb);
  2292.    hp = CreatePenIndirect(&(wc->pen));
  2293.    if (stdwin) oldpen = SelectObject(stddc, hp);
  2294.    oldpen2 = SelectObject(pixdc, hp);
  2295.    if (stdwin) {
  2296.       SetBkMode(stddc, wc->bkmode);
  2297.       for (i = 0; i < nsegs; i++) {
  2298.      Polyline(stddc, (POINT *)(segs+i), 2);
  2299.      }
  2300.       }
  2301.    SetBkMode(pixdc, wc->bkmode);
  2302.    for (i = 0; i < nsegs; i++) {
  2303.       Polyline(pixdc, (POINT *)(segs+i), 2);
  2304.       }
  2305.    if (stdwin) SelectObject(stddc, oldpen);
  2306.    SelectObject(pixdc, oldpen2);
  2307.    DeleteObject(hp);
  2308.    FREE_STDLOCALS(wb);
  2309.    return;
  2310.    }
  2311.  
  2312.  
  2313. /*
  2314.  * drawstrng()
  2315.  */
  2316. void drawstrng(wbinding *wb, int x, int y, char *s, int slen)
  2317.    {
  2318.    STDLOCALS(wb);
  2319.  
  2320.    STDFONT;
  2321.    if (stdwin) {
  2322.       SetBkMode(stddc, TRANSPARENT);
  2323.       if (wc->fg != RGB(0, 0, 0)) SetTextColor(stddc, PALCLR(wc->fg));
  2324.       if (wc->bg != RGB(255, 255, 255)) SetBkColor(stddc, PALCLR(wc->bg));
  2325.       TextOut(stddc, x, y - ASCENT(wb), s, slen);
  2326.       }
  2327.    SetBkMode(pixdc, TRANSPARENT);
  2328.    if (wc->fg != RGB(0, 0, 0)) SetTextColor(pixdc, PALCLR(wc->fg));
  2329.    if (wc->bg != RGB(255, 255, 255)) SetBkColor(pixdc, PALCLR(wc->bg));
  2330.    TextOut(pixdc, x, y - ASCENT(wb), s, slen);
  2331.  
  2332.    FREE_STDLOCALS(wb);
  2333.    return;
  2334.    }
  2335.  
  2336.  
  2337. /*
  2338.  * fillarcs
  2339.  */
  2340. void fillarcs(wbp wb, XArc *arcs, int narcs) 
  2341.    {
  2342.    register XArc *arc = arcs;
  2343.    int i, diff, bheight;
  2344.    HBRUSH hb, oldbrush, oldbrush2;
  2345.    POINT pts[3];
  2346.    HPEN hp, oldpen, oldpen2;
  2347.    STDLOCALS(wb);
  2348.    hp = CreatePenIndirect(&(wc->pen));
  2349.    if (stdwin) oldpen = SelectObject(stddc, hp);
  2350.    oldpen2 = SelectObject(pixdc, hp);
  2351.    hb = CreateBrushIndirect(&(wc->brush));
  2352.    if (stdwin) oldbrush = SelectObject(stddc, hb);
  2353.    oldbrush2 = SelectObject(pixdc, hb);
  2354.    for (i = 0; i < narcs; i++, arc++) {
  2355.       if (arc->angle2 >= 2 * Pi) {
  2356.      if (stdwin) 
  2357.         Ellipse(stddc, arc->x, arc->y, 
  2358.             arc->x + arc->width, arc->y + arc->height);
  2359.      Ellipse(pixdc, arc->x, arc->y, 
  2360.          arc->x + arc->width, arc->y + arc->height);
  2361.      }
  2362.       else {
  2363.      arc->angle1 = -arc->angle1 - arc->angle2;
  2364.      pts[0].x = arc->x + (arc->width>>1);
  2365.      pts[0].y = arc->y + (arc->height>>1);
  2366.      pts[1].x = arc->x + (arc->width>>1) + (int)(((arc->width + 1)>>1) * cos(arc->angle1));
  2367.      pts[1].y = arc->y + (arc->height>>1) - (int)(((arc->height )>>1) * sin(arc->angle1));
  2368.      pts[2].x = arc->x + (arc->width>> 1) + (int)(((arc->width + 1)>>1) * cos(arc->angle1+arc->angle2));
  2369.      pts[2].y = arc->y + (arc->height>>1) - (int)(((arc->height )>>1) * sin(arc->angle1+arc->angle2));
  2370.      if (stdwin) {
  2371.         Pie(stddc, arc->x, arc->y,
  2372.         arc->x + arc->width, arc->y + arc->height,
  2373.         pts[1].x, pts[1].y, pts[2].x, pts[2].y);
  2374.         }
  2375.      Pie(pixdc, arc->x, arc->y,
  2376.          arc->x + arc->width, arc->y + arc->height,
  2377.         pts[1].x, pts[1].y, pts[2].x, pts[2].y);
  2378.      }
  2379.       }
  2380.    if (stdwin) SelectObject(stddc, oldpen);
  2381.    SelectObject(pixdc, oldpen2);
  2382.    DeleteObject(hp);
  2383.    if (stdwin) SelectObject(stddc, oldbrush);
  2384.    SelectObject(pixdc, oldbrush2);
  2385.    DeleteObject(hb);
  2386.    FREE_STDLOCALS(wb);
  2387.    return;
  2388.    }
  2389.  
  2390. /*
  2391.  * fillrectangles
  2392.  */
  2393. void fillrectangles(wbp wb, XRectangle *recs, int nrecs)
  2394.    {
  2395.    int i, diff, bheight;
  2396.    HBRUSH hb, oldbrush, oldbrush2;
  2397.    STDLOCALS(wb);
  2398.    hb = CreateBrushIndirect(&(wc->brush));
  2399.    if (stdwin) oldbrush = SelectObject(stddc, hb);
  2400.    oldbrush2 = SelectObject(pixdc, hb);
  2401.    for (i = 0; i < nrecs; i++) {
  2402.       recs[i].right += recs[i].left;
  2403.       recs[i].bottom += recs[i].top;
  2404.       if (stdwin) FillRect(stddc, (recs+i), hb);
  2405.       FillRect(pixdc, (recs+i), hb);
  2406.       }
  2407.    if (stdwin) SelectObject(stddc, oldbrush);
  2408.    SelectObject(pixdc, oldbrush2);
  2409.    DeleteObject(hb);
  2410.    FREE_STDLOCALS(wb);
  2411.    return;
  2412.    }
  2413.  
  2414.  
  2415. /*
  2416.  * drawrectangles - draw nrecs # of rectangles in array recs to binding w
  2417.  */
  2418. void drawrectangles(wbp w, XRectangle *recs, int nrecs)
  2419.    {
  2420.    register XRectangle *r;
  2421.    LOGBRUSH lb;
  2422.    HBRUSH hb, oldbrush, oldbrush2;
  2423.    HPEN hp, oldpen, oldpen2;
  2424.    STDLOCALS(w);
  2425.    hp = CreatePenIndirect(&(wc->pen));
  2426.    if (stdwin) oldpen = SelectObject(stddc, hp);
  2427.    oldpen2 = SelectObject(pixdc, hp);
  2428.    lb.lbStyle = BS_NULL;
  2429.    hb = CreateBrushIndirect(&lb);
  2430.    if (stdwin) oldbrush = SelectObject(stddc, hb);
  2431.    oldbrush2 = SelectObject(pixdc, hb);
  2432.    for (r = recs; r < recs + nrecs; r++) {
  2433.       r->right += r->left + 1;
  2434.       r->bottom += r->top + 1;
  2435.       if (stdwin) Rectangle(stddc, r->left, r->top, r->right, r->bottom);
  2436.       Rectangle(pixdc, r->left, r->top, r->right, r->bottom);
  2437.       }
  2438.    if (stdwin) SelectObject(stddc, oldpen);
  2439.    SelectObject(pixdc, oldpen2);
  2440.    DeleteObject(hp);
  2441.    if (stdwin) SelectObject(stddc, oldbrush);
  2442.    SelectObject(pixdc, oldbrush2);
  2443.    DeleteObject(hb);
  2444.    FREE_STDLOCALS(w);
  2445.    return;
  2446.    }
  2447.  
  2448. /*
  2449.  * fillpolygon
  2450.  */
  2451. void fillpolygon(wbp w, XPoint *pts, int npts)
  2452.    {
  2453.    HBRUSH hb, oldbrush;
  2454.    HPEN hp, oldpen, oldpen2;
  2455.    STDLOCALS(w);
  2456.    hp = CreatePenIndirect(&(wc->pen));
  2457.    if (stdwin) oldpen = SelectObject(stddc, hp);
  2458.    oldpen2 = SelectObject(pixdc, hp);
  2459.    hb = CreateBrushIndirect(&(wc->brush));
  2460.    if (stdwin) {
  2461.       oldbrush = SelectObject(stddc, hb);
  2462.       Polygon(stddc, pts, npts);
  2463.       SelectObject(stddc, oldbrush);
  2464.       }
  2465.    oldbrush = SelectObject(pixdc, hb);
  2466.    Polygon(pixdc, pts, npts);
  2467.    SelectObject(pixdc, oldbrush);
  2468.    DeleteObject(hb);
  2469.    if (stdwin) SelectObject(stddc, oldpen);
  2470.    SelectObject(pixdc, oldpen2);
  2471.    DeleteObject(hp);
  2472.    FREE_STDLOCALS(w);
  2473.    }
  2474.  
  2475. LONG NumWindows = 0;
  2476.  
  2477.  
  2478. /*
  2479.  * allocate a context.  Can't be called until w has a display and window.
  2480.  */
  2481. wcp alc_context(w)
  2482. wbp w;
  2483.    {
  2484.    int i;
  2485.    wcp wc;
  2486.  
  2487.    GRFX_ALLOC(wc, _wcontext);
  2488.  
  2489.    wc->bkmode = OPAQUE;        /* at present, only used in line drawing */
  2490.    wc->fg = RGB(0,0,0);
  2491.    wc->bg = RGB(255,255,255);
  2492.    wc->fgname = salloc("black");
  2493.    wc->bgname = salloc("white");
  2494.    wc->pen.lopnStyle = PS_SOLID;
  2495.    wc->pen.lopnWidth.x = wc->pen.lopnWidth.y = 1;
  2496.    wc->pen.lopnColor = PALCLR(wc->fg);
  2497.    wc->bgpen.lopnStyle = PS_SOLID;
  2498.    wc->bgpen.lopnWidth.x = wc->bgpen.lopnWidth.y = 1;
  2499.    wc->bgpen.lopnColor = PALCLR(wc->bg);
  2500.    wc->fillstyle = BS_SOLID;
  2501.    wc->brush.lbStyle = BS_SOLID;
  2502.    wc->brush.lbColor = PALCLR(wc->fg);
  2503.    wc->bgbrush.lbStyle = BS_SOLID;
  2504.    wc->bgbrush.lbColor = PALCLR(wc->bg);
  2505.    wc->gamma = GammaCorrection;
  2506.    wc->drawop = R2_COPYPEN;
  2507.    wc->font = (wfp)alloc(sizeof (struct _wfont));
  2508.    wc->font->name = salloc("fixed");
  2509.    wc->font->font = CreateFont(16,0,0,0,FW_NORMAL,0,0,0,DEFAULT_CHARSET,
  2510.      OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
  2511.      DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, NULL);
  2512.  
  2513.    wc->font->charwidth = 8;
  2514.    wc->leading = 16;
  2515.  
  2516.    GRFX_LINK(wc, wcntxts);
  2517.    return wc;
  2518.    }
  2519.  
  2520. /*
  2521.  * allocate a context, cloning attributes from an existing context
  2522.  */
  2523. wcp clone_context(w)
  2524. wbp w;
  2525.    {
  2526.    wcp wc, wc2 = w->context;
  2527.    wsp ws = w->window;
  2528.    wbinding tmp;
  2529.    int i;
  2530.  
  2531.    GRFX_ALLOC(wc, _wcontext);
  2532.  
  2533.    tmp.window = ws;
  2534.    tmp.context = wc;
  2535.    /*
  2536.     * copy over some stuff
  2537.     */
  2538.    wc->clipx = wc2->clipx;
  2539.    wc->clipy = wc2->clipy;
  2540.    wc->clipw = wc2->clipw;
  2541.    wc->cliph = wc2->cliph;
  2542.    wc->dx = wc2->dx;
  2543.    wc->dy = wc2->dy;
  2544.    if (wc2->patternname)
  2545.       wc->patternname = salloc(wc2->patternname);
  2546.    /* clone needs to make a copy of the pattern */
  2547.    wc->bkmode = wc2->bkmode;
  2548.    wc->fg = wc2->fg;
  2549.    wc->bg = wc2->bg;
  2550.    wc->fgname = salloc(wc2->fgname);
  2551.    wc->bgname = salloc(wc2->bgname);
  2552.    wc->pen = wc2->pen;
  2553.    if (ISXORREVERSEW(wc)) {
  2554.       wc->brush.lbColor = PALCLR((wc->fg ^ wc->bg) & 0x00FFFFFF);
  2555.       }
  2556.    else {
  2557.       wc->brush.lbColor = PALCLR(wc->fg);
  2558.       }
  2559.    wc->bgpen = wc2->bgpen;
  2560.    wc->fillstyle = wc2->fillstyle;
  2561.    wc->brush.lbStyle = wc->fillstyle;
  2562.    wc->bgbrush.lbStyle = wc->fillstyle;
  2563.    wc->bgbrush.lbColor = PALCLR(wc->bg);
  2564.    wc->gamma = wc2->gamma;
  2565.    wc->drawop = wc2->drawop;
  2566.    wc->font = (wfp)alloc(sizeof (struct _wfont));
  2567.    wc->font->name = salloc("fixed");
  2568.    wc->font->font = CreateFont(13,0,0,0,FW_NORMAL,0,0,0,DEFAULT_CHARSET,
  2569.      OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
  2570.      DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, NULL);
  2571.    wc->leading = wc2->leading;
  2572.    setfont(&tmp, &(wc2->font->name));
  2573.  
  2574.    GRFX_LINK(wc, wcntxts);
  2575.    return wc;
  2576.    }
  2577.  
  2578. /*
  2579.  * allocate a window state structure
  2580.  */
  2581. wsp alc_winstate()
  2582.    {
  2583.    int i;
  2584.    wsp ws;
  2585.    
  2586.    GRFX_ALLOC(ws, _wstate);
  2587.    ws->bits = 1024;                             /* echo ON; others OFF */
  2588.    ws->filep = nulldesc;
  2589.    ws->listp = nulldesc;
  2590.  
  2591.    GRFX_LINK(ws, wstates);
  2592.    return ws;
  2593.    }
  2594.  
  2595. /*
  2596.  * free a window state
  2597.  */
  2598. int free_window(ws)
  2599. wsp ws;
  2600.    {
  2601.    ws->refcount--;
  2602.    if(ws->refcount == 0) {
  2603.       if (ws->win) /* && IsWindowVisible(ws->win))*/
  2604.      DestroyWindow(ws->win);
  2605. /*      ws->win = 0;*/
  2606.       if (ws->iconwin && ws->iconwin != ws->win) {
  2607.          if (IsWindowVisible(ws->iconwin))
  2608.         DestroyWindow(ws->iconwin);
  2609.          else DestroyWindow(ws->iconwin);
  2610.      }
  2611. /*      ws->iconwin = 0;*/
  2612. /*      while (ws->win)
  2613.      if (pollevent() == -1) return -1;
  2614. */
  2615.       if (ws->pix)
  2616.      DeleteObject(ws->pix);
  2617.       ws->pix = 0;
  2618.       if (ws->iconpix)
  2619.      DeleteObject(ws->iconpix);
  2620.       ws->iconpix = 0;
  2621.       if (ws->initialPix)
  2622.      DeleteObject(ws->initialPix);
  2623.       ws->initialPix = 0;
  2624.       GRFX_UNLINK(ws, wstates);
  2625.       }
  2626.    return 0;
  2627.    }
  2628.  
  2629. /*
  2630.  * free a window context
  2631.  */
  2632. novalue free_context(wc)
  2633. wcp wc;
  2634.    {
  2635.    wc->refcount--;
  2636.    if(wc->refcount == 0) {
  2637.       if (wc->cliprgn)
  2638.      DeleteObject(wc->cliprgn);
  2639.       wc->cliprgn = 0;
  2640.       if (wc->pattern)
  2641.      DeleteObject(wc->pattern);
  2642.       wc->pattern = 0;
  2643.       if (wc->font) {
  2644.      if (wc->font->font)
  2645.         DeleteObject(wc->font->font);
  2646.      wc->font->font = 0;
  2647.      if (wc->font->name)
  2648.         free(wc->font->name);
  2649.      wc->font->name = 0;
  2650.      free(wc->font);
  2651.      }
  2652.       wc->font = 0;
  2653.       if (wc->fgname) free(wc->fgname);
  2654.       wc->fgname = 0;
  2655.       if (wc->bgname) free(wc->bgname);
  2656.       wc->bgname = 0;
  2657.       GRFX_UNLINK(wc, wcntxts);
  2658.       }
  2659.    }
  2660.  
  2661. int walert(wbp w, int volume)
  2662.    {
  2663.    MessageBeep(0);
  2664.    }
  2665.  
  2666. int patbits[] = {
  2667.   0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  2668.   0xFE,0xFF,0xEF,0xFF,0xFE,0xFF,0xEF,0xFF,
  2669.   0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,
  2670.   0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,
  2671.   0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,
  2672.   0x01,0x00,0x10,0x00,0x01,0x00,0x10,0x00,
  2673.   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  2674.  
  2675.   0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
  2676.   0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,
  2677.   0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,
  2678.   0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x10,
  2679.   0x82,0x44,0x28,0x10,0x28,0x44,0x82,0x01,
  2680.  
  2681.   0x0F,0x0F,0x0F,0x0F,0xF0,0xF0,0xF0,0xF0,
  2682.   0x1B,0x18,0x81,0xB1,0x36,0x06,0x60,0x63,
  2683.   0x02,0x02,0x05,0xF8,0x20,0x20,0x50,0x8F,
  2684.   0x03,0x84,0x48,0x30,0x03,0x84,0x48,0x30,
  2685. };
  2686.  
  2687. /*
  2688.  * SetPattern
  2689.  */
  2690. int SetPattern(w, name, len)
  2691. wbp w;
  2692. char *name;
  2693. int len;
  2694.    {
  2695.    int width, nbits;
  2696.    int i, j;
  2697.    int symbol;
  2698.    C_integer v, bits[MAXXOBJS];
  2699.    HBITMAP p;
  2700.    char data[MAXXOBJS];
  2701.    char *buf = data;
  2702.    wcp wc = w->context;
  2703.  
  2704.    if (wc->patternname != NULL)
  2705.       free(wc->patternname);
  2706.    wc->patternname = malloc(len+1);
  2707.    mystrncpy(wc->patternname, name, len);
  2708.    
  2709.    /*
  2710.     * If the pattern starts with a number it is a width , bits encoding
  2711.     */
  2712.    if ((len > 0) && isdigit(name[0])) {
  2713.       nbits = MAXXOBJS;
  2714.       switch (parsepattern(name, len, &width, &nbits, bits)) {
  2715.       case Failed:
  2716.      return Failed;
  2717.       case Error:
  2718.      ReturnErrNum(145, Error);
  2719.      }
  2720.       if (w->window->iconwin == NULL) return Succeeded;
  2721.       return SetPatternBits(w, width, bits, nbits);
  2722.       }
  2723.  
  2724.    /*
  2725.     * Otherwise, it is a named pattern.  Find the symbol id.
  2726.     */
  2727.    if ((symbol = si_s2i(siPatternSyms, wc->patternname)) >= 0) {
  2728.       if (w->window->iconwin == NULL) return Succeeded;
  2729.       for(i = 0; i < 8; i++) {
  2730.      v = ~(patbits[symbol * 8 + i]);
  2731.      *buf++ = v;
  2732.      }
  2733.       p = CreateBitmapFromData(data);
  2734.       if (wc->pattern)
  2735.      DeleteObject(wc->pattern);
  2736.       wc->pattern = p;
  2737.       if (wc->fillstyle == BS_PATTERN) {
  2738.      wc->brush.lbStyle = BS_PATTERN;
  2739.      wc->brush.lbColor = PALCLR(wc->fg);
  2740.      wc->brush.lbHatch = p;
  2741.      }     
  2742.       return Succeeded;
  2743.       }
  2744.    ReturnErrNum(145, Error);
  2745.    }
  2746.  
  2747. /*
  2748.  * Create an 8x8 bitmap from some data
  2749.  */
  2750. HBITMAP CreateBitmapFromData(char *data)
  2751. {
  2752.    WORD *wBits = alloc(8 * sizeof(WORD));
  2753.    HBITMAP rv;
  2754.    int i;
  2755.    static BITMAP bitmap = { 0, 8, 8, 2, 1, 1};
  2756.    for (i = 0; i < 8; i++)
  2757.       wBits[i] = data[i];
  2758.    bitmap.bmBits = (LPSTR) wBits;
  2759.    rv = CreateBitmapIndirect(&bitmap);
  2760.    free(wBits);
  2761.    return rv;
  2762. }
  2763.  
  2764.  
  2765. int SetPatternBits(w, width, bits, nbits)
  2766. wbp w;
  2767. int width;
  2768. C_integer *bits;
  2769. int nbits;
  2770.    {
  2771.    C_integer v;
  2772.    int i, j;
  2773.    HBITMAP p;
  2774.    char data[MAXXOBJS];
  2775.    char *buf = data;
  2776.    wcp wc = w->context;
  2777.  
  2778.    if (width != 8 || nbits != 8)
  2779.       return Failed;
  2780.  
  2781.    for(i = 0; i < nbits; i++) {
  2782.       v = bits[i];
  2783.       for(j=0; j<width; j+=8) {
  2784.      *buf++ = v;
  2785.      v >>= 8;
  2786.      }
  2787.       }
  2788.  
  2789.    p = CreateBitmapFromData(data);
  2790.    if (wc->pattern)
  2791.       DeleteObject(wc->pattern);
  2792.    wc->pattern = p;
  2793.    if (wc->fillstyle == BS_PATTERN) {
  2794.       wc->brush.lbStyle = BS_PATTERN;
  2795.       wc->brush.lbColor = PALCLR(wc->fg);
  2796.       wc->brush.lbHatch = p;
  2797.       }     
  2798.    return Succeeded;
  2799.    }
  2800.  
  2801. int pixmap_init(w)
  2802. wbp w;
  2803.    {
  2804.    wsp ws = w->window;
  2805.    resizePixmap(w, ws->width, ws->height);
  2806.    return Succeeded;
  2807.    }
  2808.  
  2809.  
  2810. int do_config(w, status)
  2811. wbp w;
  2812. int status;
  2813.    {
  2814.    wsp ws = w->window;
  2815.    int wid = ws->width, ht = ws->height;
  2816.    int posx = ws->posx, posy = ws->posy;
  2817.    if (! resizePixmap(w, wid, ht))
  2818.       return Failed;
  2819.    if (ws->win) {
  2820.       pollevent();
  2821.       if (status == 3) {
  2822.      SetWindowPos(ws->win, ws->win, posx, posy,
  2823.               wid + BORDWIDTH, ht + BORDHEIGHT, SWP_NOZORDER);
  2824.      }
  2825.       else if (status == 2)
  2826.      SetWindowPos(ws->win, ws->win, 0, 0,
  2827.               wid + BORDWIDTH, ht + BORDHEIGHT, SWP_NOMOVE|SWP_NOZORDER);
  2828.       else if (status == 1)
  2829.      SetWindowPos(ws->win, ws->win, posx, posy, 0, 0, SWP_NOSIZE|SWP_NOZORDER);
  2830.       }
  2831.    return Succeeded;
  2832.    }
  2833.  
  2834. /*
  2835.  * UpdateCursorPos
  2836.  */
  2837. void UpdateCursorPos(wsp ws, wcp wc)
  2838. {
  2839. }
  2840.  
  2841. int resizePixmap(wbp w, int width, int height)
  2842.    {
  2843.    HDC hdc, hdc2, hdc3;
  2844.    HBITMAP newpix;
  2845.    HBRUSH hb;
  2846.    LOGBRUSH lb;
  2847.    XRectangle rect;
  2848.    wsp ws = w->window;
  2849.    int x = ws->pixwidth, y = ws->pixheight;
  2850.    if (ISEXPOSED(w)) {
  2851.       if (ws->pixwidth >= width && ws->pixheight >= height) {
  2852.          return 1;
  2853.          }
  2854.       ws->pixheight = max(ws->pixheight, height);
  2855.       ws->pixwidth = max(ws->pixwidth, width);
  2856.       }
  2857.    else {
  2858.       ws->pixwidth = width;
  2859.       ws->pixheight = height;
  2860.       }
  2861.    hdc = GetDC(ws->iconwin);
  2862.    newpix = CreateCompatibleBitmap (hdc, ws->pixwidth, ws->pixheight);
  2863.    if (ws->pix) {
  2864.       hdc2 = CreateCompatibleDC(hdc);
  2865.       SelectObject(hdc2, ws->pix);
  2866.       }
  2867.    hdc3 = CreateCompatibleDC(hdc);
  2868.    SelectObject(hdc3, newpix);
  2869.    if (palette) {
  2870.       SelectPalette(hdc, palette, FALSE);
  2871.       if (ws->pix) SelectPalette(hdc2, palette, FALSE);
  2872.       SelectPalette(hdc3, palette, FALSE);
  2873.       RealizePalette(hdc);
  2874.       if (ws->pix) RealizePalette(hdc2);
  2875.       RealizePalette(hdc3);
  2876.       }
  2877.    lb.lbStyle = BS_SOLID;
  2878.    lb.lbColor = PALCLR(w->context->bg);
  2879.    hb = CreateBrushIndirect(&lb);
  2880.    /*
  2881.     * initialize the new pixmap, including areas not in the old pixmap.
  2882.     */
  2883.    rect.left = 0; rect.right = ws->pixwidth;
  2884.    rect.top = 0; rect.bottom = ws->pixheight;
  2885.    FillRect(hdc3, &rect, hb);
  2886.    if (ws->win)
  2887.       FillRect(hdc, &rect, hb);
  2888.  
  2889.    if (ws->pix) BitBlt(hdc3, 0, 0, x - 2, y - 1, hdc2, 0, 0, SRCCOPY);
  2890.    if (ws->win)
  2891.       BitBlt(hdc, 0, 0, ws->pixwidth, ws->pixheight, hdc3, 0, 0, SRCCOPY);
  2892.    DeleteDC(hdc3);
  2893.    if (ws->pix) DeleteDC(hdc2);
  2894.    ReleaseDC(ws->iconwin, hdc);
  2895.    if (ws->pix) DeleteObject(ws->pix);
  2896.    DeleteObject(hb);
  2897.    ws->pix = newpix;   
  2898.    return 1;
  2899.    }
  2900.  
  2901. /*
  2902.  * CreateWinDC - create a device context for drawing on the window
  2903.  *  In addition, select objects specified by flags.
  2904.  */
  2905. HDC CreateWinDC(wbp w)
  2906.    {
  2907.    wsp ws = w->window;
  2908.    wcp wc = w->context;
  2909.    HDC hdc = GetDC(ws->iconwin);
  2910.    if (numColors > 0) {
  2911.       SelectPalette(hdc, palette, FALSE);
  2912. /*      UnrealizeObject(palette); */
  2913. RealizePalette(hdc);
  2914.       if (numRealized < numColors) {
  2915.          numRealized = numColors;
  2916.          if (RealizePalette(hdc) == 0) /* noop */;
  2917. /*        return NULL; */
  2918.          }
  2919.       }
  2920.    SetROP2(hdc, wc->drawop);
  2921.    if (wc->clipw >= 0){
  2922.       SelectClipRgn(hdc, wc->cliprgn);
  2923.       }
  2924.    return hdc;
  2925.    }
  2926.  
  2927. HDC CreatePixDC(wbp w, HDC hdc)
  2928.    {
  2929.    wsp ws = w->window;
  2930.    wcp wc = w->context;
  2931.    HDC hdc2 = CreateCompatibleDC(hdc);
  2932.    if (numColors > 0) {
  2933.       SelectPalette(hdc2, palette, FALSE);
  2934. RealizePalette(hdc2);
  2935.       }
  2936.    SelectObject(hdc2, w->window->pix);
  2937.    SetROP2(hdc2, wc->drawop);
  2938.    if (wc->clipw >= 0){
  2939.       SelectClipRgn(hdc2, wc->cliprgn);
  2940.       }
  2941.    return hdc2;
  2942.    }
  2943.  
  2944. int setinputmask(wbp w, char *val)
  2945. {
  2946.    wsp ws = w->window;
  2947.    if (strchr(val,'m')) {
  2948. /*      ws->inputmask |= PointerMotionMask;
  2949.       if (ws->win)
  2950.      XSelectInput(ws->display->display, ws->win, ws->inputmask); */
  2951.       }
  2952.    else {
  2953. /*      ws->inputmask &= ~PointerMotionMask;
  2954.       if (ws->win)
  2955.      XSelectInput(ws->display->display, ws->win, ws->inputmask); */
  2956.       }
  2957.    return Succeeded;
  2958. }
  2959.  
  2960. /*
  2961.  * compute a text width for a current device context (typically pixdc)
  2962.  */
  2963. int dc_textwidth(HDC dc, char *s, int n)
  2964. {
  2965.    SIZE sz;
  2966.    /*
  2967.     * GetTextExtentPoint32(dc, s, n, &sz) gives incorrect behavior
  2968.     *  under Win32s
  2969.     */
  2970.    GetTextExtentPoint(dc, s, n, &sz);
  2971.    return (int)sz.cx;
  2972. }
  2973.  
  2974. int textWidth(wbp w, char *s, int n)
  2975.    {
  2976.    int rv;
  2977.    wsp ws = w->window;
  2978.    HDC stddc = GetDC(ws->iconwin);
  2979.    SelectObject(stddc, w->context->font->font);
  2980.    rv = dc_textwidth(stddc, s, n);
  2981.    ReleaseDC(ws->iconwin, stddc);
  2982.    return rv;
  2983.    }
  2984.  
  2985. novalue warpPointer(w, x, y)
  2986. wbp w;
  2987. int x, y;
  2988.    {
  2989.    wsp ws = w->window;
  2990.    SetCursorPos(ws->posx + x, ws->posy + y);
  2991.    }
  2992.  
  2993. /*
  2994.  * free all Windows resources allocated by this instantiation of iconx
  2995.  */
  2996. void wfreersc()
  2997. {
  2998.    while (wstates != NULL) {
  2999.       wstates->refcount = 1;
  3000.       free_window(wstates);
  3001.       }
  3002.    while (wcntxts != NULL) {
  3003.       wcntxts->refcount = 1;
  3004.       free_context(wcntxts);
  3005.       }
  3006.    if (palette) {
  3007.       DeleteObject(palette);
  3008.       palette = 0;
  3009.       }
  3010. }
  3011.  
  3012. #else                                   /* Graphics */
  3013.   static char aaa;
  3014. #endif                                  /* Graphics */
  3015.