home *** CD-ROM | disk | FTP | other *** search
/ gondwana.ecr.mu.oz.au/pub/ / Graphics.tar / Graphics / vogleplg.zip / DRIVERS / IBMPC / MSWINEXT.C
C/C++ Source or Header  |  1994-07-17  |  20KB  |  875 lines

  1. /****************************************************************************
  2.  
  3.     PROGRAM: MSWINEXT.C
  4.  
  5.     PURPOSE: MS-Windows driver for VOGLE/VOGL
  6.              For use with a window external to VOGLE
  7.  
  8.     FUNCTIONS:
  9.  
  10.     mswinext_cleanup() - frees objects created along the way in preparation for exit
  11.     mswinext_...() - VOGLE driver routines called by VOGLE
  12.     swap(() - swaps two integer values
  13.  
  14. ****************************************************************************/
  15.  
  16. #include "windows.h"            /* required for all Windows applications */
  17. #include <stdio.h>
  18. #include "vogle.h"
  19.  
  20. #define    CMAPSIZE    256        /* max size of colour map */
  21. #define MAX_INSTANCES    10        /* max # of instances of driver */
  22. #define NO_INSTANCE    -1        /* no current instance exists */
  23. #define NO_WINDOW    0xffff        /* no window info set before vinit() */
  24.  
  25. typedef COLORREF    *PCOLORREF;    /* pointer to a bunch of coloUr refs */
  26.  
  27. typedef struct _DRIVERINFO {    /* info for driver operation */
  28.     int        nId;        /* id of this driver info structure */
  29.     HWND        hWinder;    /* handle of VOGLE's window */
  30.     HDC        hMemoryDC;    /* memory device context for hWinder */
  31.     HBITMAP        hBitmap;    /* bitmap compatible with hWinder */
  32.     unsigned int    nCurColour;    /* index of current colour in carray */
  33.     PCOLORREF    carray;        /* list of known colour values */
  34.     int        bUseFrontBuf;    /* FALSE if double buffering */
  35.     short int    xChar;        /* width of system font character */
  36.     short int    yChar;        /* height of system font character */
  37.     RECT        BackRect;    /* bitmap area to be swapped on next mswinext_swapbuf() call */
  38.     int        nLWidth;    /* line width */
  39.     } DRIVERINFO;
  40.  
  41. typedef struct _DEFERINFO {    /* info for deferred creation of VOGLE instance */
  42.     HWND        hWnd;        /* window handle */
  43.     int        w;        /* window size... */
  44.     int        h;
  45.     } DEFERINFO;
  46.  
  47. static DRIVERINFO    InstanceTable[MAX_INSTANCES];
  48. static DRIVERINFO    Inst;            /* save an indirection by storing the current instance info here */
  49. static int        nCurrentInstance = -1;    /* no current instance */
  50. static int        bInited = FALSE;    /* TRUE when init has been called at least once */
  51. static DEFERINFO    DeferInfo;        /* info deferred to later creation of instance */
  52.  
  53. /* a couple of prototypes... */
  54. static    void    InitInstances(void);
  55. static    int    FindInstance(int);
  56. static    int    mswinext_init(void);
  57. static    int    mswinext_exit(void);
  58. static    void    mswinext_cleanup(void);
  59. static    void    mswinext_invalidate_rect(LPRECT);
  60. static    int    mswinext_clear(void);
  61. static    int    mswinext_draw(int, int);
  62. static    int    mswinext_fill(int, int *, int *);
  63. static    int    mswinext_color(int);
  64. static    int    mswinext_mapcolor(int, int, int, int);
  65. static    int    mswinext_char(char);
  66. static    int    mswinext_string(char *);
  67. static    int    mswinext_font(char *);
  68. static    int    mswinext_frontbuf(void);
  69. static    int    mswinext_backbuf(void);
  70. static    int    mswinext_swapbuf(void);
  71. static    int    mswinext_setlw(int);
  72. static    int    noop(void);
  73. extern    int    _mswinext_devcpy(void);
  74. extern    int    mswin_verror(char *);
  75. static  int    mswinext_SetupInstance(HWND, int, int);
  76. extern    int    vo_mswinext_window(HWND, int, int);
  77. extern    int    vo_mswinext_win_size(int, int);
  78. extern    int    vo_mswinext_paint_window(HWND);
  79. extern    int    vo_mswinext_paint_dc(HDC);
  80. static    void    swap(int *, int *);
  81.  
  82. #ifdef MSC
  83. #if (_MSC_VER >= 800)
  84. #define strdup _strdup
  85. #endif
  86. #endif
  87. char            *strdup(char *);
  88.  
  89.  
  90. static
  91. void        InitInstances()
  92. {
  93.     int    i;
  94.     for (i = 0; i < MAX_INSTANCES; i++) {
  95.         InstanceTable[i].nId = NO_INSTANCE;
  96.         InstanceTable[i].carray = NULL;
  97.         InstanceTable[i].hWinder = NULL;
  98.         }
  99.     nCurrentInstance = NO_INSTANCE;
  100. }
  101.  
  102.  
  103.  
  104. static
  105. int        FindInstance(int nId)
  106. {
  107.     int    i;
  108.  
  109.     for (i = 0; i < MAX_INSTANCES; i++) {
  110.         if (nId == InstanceTable[i].nId) {
  111.             /* found the required instance */
  112.             return i;
  113.             }
  114.         }
  115.  
  116.     return NO_INSTANCE;
  117. }
  118.  
  119.  
  120.  
  121. /*
  122.  * Save the state of an instance and return an instance
  123.  * identfier (for later restoration).
  124.  */
  125. int        SaveInstance()
  126. {
  127.     int    n;
  128.  
  129.     if ((n = nCurrentInstance) != NO_INSTANCE) {
  130.         /* save current instance in instance table */
  131.         InstanceTable[nCurrentInstance] = Inst;
  132.         /* now we have no current instance */
  133.         nCurrentInstance = NO_INSTANCE;
  134.         }
  135.  
  136.     return n;
  137. }
  138.  
  139.  
  140.  
  141. /*
  142.  * Restore an instance given a valid instance identifier.
  143.  * We won't restore an instance if there is a current one
  144.  * (call SaveInstance() first).
  145.  */
  146. int        RestoreInstance(int nId)
  147. {
  148.     if (nId < 0 || nId >= MAX_INSTANCES || nCurrentInstance != NO_INSTANCE) {
  149.         return NO_INSTANCE;
  150.         }
  151.  
  152.     /* make sure we are using a valid instance id */
  153.     if (InstanceTable[nId].nId == NO_INSTANCE) return NO_INSTANCE;
  154.  
  155.     /* restore the instance */
  156.     Inst = InstanceTable[nCurrentInstance = nId];
  157.  
  158.     return nId;
  159. }
  160.  
  161.  
  162.  
  163. static int    mswinext_init()
  164. {
  165.     HDC        hDC;
  166.     PCOLORREF    carray;
  167.  
  168.     if (!bInited) {
  169.         /* do once off initialization */
  170.         InitInstances();
  171.         bInited = TRUE;
  172.         }
  173.  
  174.     if (DeferInfo.hWnd == NO_WINDOW) {
  175.         /* we have no info for which to init VOGLE - cark */
  176.         return FALSE;
  177.         }
  178.  
  179.     if (nCurrentInstance != NO_INSTANCE) {
  180.         /* zap current instance - too bad - user didn't save it */
  181.         mswinext_exit();
  182.         }
  183.  
  184.     /* find a free instance */
  185.     nCurrentInstance = FindInstance(NO_INSTANCE);
  186.     if (nCurrentInstance == NO_INSTANCE) {
  187.         /* we've run out of available instances, cark it */
  188.         return FALSE;
  189.         }
  190.     Inst = InstanceTable[nCurrentInstance];
  191.  
  192.     /* allocate the instance */
  193.     Inst.nId = nCurrentInstance;
  194.  
  195.     /* find bit depth */
  196.     hDC = GetDC(GetDesktopWindow());
  197.     vdevice.depth = GetDeviceCaps(hDC, PLANES);
  198.     ReleaseDC(GetDesktopWindow(), hDC);
  199.  
  200.     /* set up colour indices */
  201.     if (carray = (PCOLORREF)calloc(sizeof(COLORREF), CMAPSIZE)) {
  202.         carray[0] = RGB(  0,   0,   0);
  203.         carray[1] = RGB(255,   0,   0);
  204.         carray[2] = RGB(  0, 255,   0);
  205.         carray[3] = RGB(255, 255,   0);
  206.         carray[4] = RGB(  0,   0, 255);
  207.         carray[5] = RGB(255,   0, 255);
  208.         carray[6] = RGB(  0, 255, 255);
  209.         carray[7] = RGB(255, 255, 255);
  210.         }
  211.  
  212.     /* zap current instance info*/
  213.     Inst.carray = carray;
  214.     Inst.hWinder = (HWND)NULL;
  215.     Inst.hMemoryDC = (HDC)NULL;
  216.     Inst.hBitmap = (HBITMAP)NULL;
  217.     Inst.nCurColour = 1;
  218.     Inst.bUseFrontBuf = TRUE;
  219.     Inst.xChar = 0;
  220.     Inst.yChar = 0;
  221.     Inst.nLWidth = 1;
  222.     InstanceTable[nCurrentInstance] = Inst;
  223.  
  224.     mswinext_SetupInstance(DeferInfo.hWnd, DeferInfo.w, DeferInfo.h);
  225.  
  226.     return TRUE;
  227. }
  228.  
  229.  
  230.  
  231. static int    mswinext_exit()
  232. {
  233.     if (nCurrentInstance == NO_INSTANCE) return -1;
  234.  
  235.     mswinext_cleanup();
  236.  
  237.     /* deallocate the current instance */
  238.     if (Inst.carray) free(Inst.carray);
  239.     Inst.nId = NO_INSTANCE;
  240.     Inst.carray = NULL;
  241.     Inst.hWinder = NULL;
  242.     InstanceTable[nCurrentInstance] = Inst;
  243.     nCurrentInstance = NO_INSTANCE;
  244.  
  245.     return 1;
  246. }
  247.  
  248.  
  249. static
  250. void        mswinext_cleanup()
  251. {
  252.     if (nCurrentInstance == NO_INSTANCE) return;
  253.  
  254.     if (Inst.hBitmap) {
  255.         DeleteObject(Inst.hBitmap);
  256.         Inst.hBitmap = (HBITMAP)NULL;
  257.         }
  258.  
  259.     if (Inst.hMemoryDC) {
  260.         DeleteDC(Inst.hMemoryDC);
  261.         Inst.hMemoryDC = (HDC)NULL;
  262.         }
  263.  
  264.     return;
  265. }
  266.  
  267.  
  268.  
  269. static
  270. void        mswinext_invalidate_rect(LPRECT r)
  271. {
  272.     if (r->left < Inst.BackRect.left) Inst.BackRect.left = r->left;
  273.     if (r->right > Inst.BackRect.right) Inst.BackRect.right = r->right;
  274.     if (r->top < Inst.BackRect.top) Inst.BackRect.top = r->top;
  275.     if (r->bottom > Inst.BackRect.bottom) Inst.BackRect.bottom = r->bottom;
  276. }
  277.  
  278.  
  279.  
  280. #ifdef VOGLE
  281. static
  282. int        mswinext_clear()
  283. {
  284.     HDC    hDC;
  285.     RECT    r;
  286.     HBRUSH    hBrush,
  287.         hOldBrush;
  288.     HBITMAP    hOldBitmap;
  289.  
  290.     if (nCurrentInstance == NO_INSTANCE) return -1;
  291.  
  292.     hOldBitmap = SelectObject(Inst.hMemoryDC, Inst.hBitmap);
  293.     GetClientRect(Inst.hWinder, &r);
  294.     hBrush = CreateSolidBrush(Inst.carray[Inst.nCurColour]);
  295.     if (hBrush) {
  296.         hOldBrush = SelectObject(Inst.hMemoryDC, hBrush);
  297.         FillRect(Inst.hMemoryDC, &r, Inst.hBrush);
  298.         if (Inst.bUseFrontBuf) {
  299.             hDC = GetDC(Inst.hWinder);
  300.             BitBlt(hDC,
  301.                 r.left, r.top,
  302.                 r.right - r.left,
  303.                 r.bottom - r.top,
  304.                 Inst.hMemoryDC,
  305.                 r.left, r.top,
  306.                 SRCCOPY);
  307.             ReleaseDC(Inst.hWinder, hDC);
  308.             }
  309.         else {
  310.             /* invalidate the region in front buffer */
  311.             mswinext_invalidate_rect(&r);
  312.             }
  313.         SelectObject(Inst.hMemoryDC, hOldBrush);
  314.         DeleteObject(hBrush);
  315.         }
  316.     SelectObject(Inst.hMemoryDC, Inst.hOldBitmap);
  317. }
  318. #else
  319. /* VOGL */
  320. static
  321. int    mswinext_clear()
  322. {
  323.     HDC    hDC;
  324.     RECT    r;
  325.     HBRUSH    hBrush,
  326.         hOldBrush;
  327.     HBITMAP    hOldBitmap;
  328.  
  329.     if (nCurrentInstance == NO_INSTANCE) return -1;
  330.  
  331.     /* rectangle describing current viewport */
  332.     r.left = vdevice.minVx;
  333.     r.top = vdevice.sizeSy - vdevice.maxVy;
  334.     r.right = vdevice.maxVx - vdevice.minVx;
  335.     r.bottom = vdevice.maxVy - vdevice.minVy;
  336.  
  337.     hOldBitmap = SelectObject(Inst.hMemoryDC, Inst.hBitmap);
  338.     hBrush = CreateSolidBrush(Inst.carray[Inst.nCurColour]);
  339.     if (hBrush) {
  340.         hOldBrush = SelectObject(Inst.hMemoryDC, hBrush);
  341.         FillRect(Inst.hMemoryDC, &r, hBrush);
  342.         if (Inst.bUseFrontBuf) {
  343.             hDC = GetDC(Inst.hWinder);
  344.             BitBlt(hDC,
  345.                 r.left, r.top,
  346.                 r.right - r.left,
  347.                 r.bottom - r.top,
  348.                 Inst.hMemoryDC,
  349.                 r.left, r.top,
  350.                 SRCCOPY);
  351.             ReleaseDC(Inst.hWinder, hDC);
  352.             }
  353.         else {
  354.             /* invalidate the region in front buffer */
  355.             mswinext_invalidate_rect(&r);
  356.             }
  357.         SelectObject(Inst.hMemoryDC, hOldBrush);
  358.         DeleteObject(hBrush);
  359.         }
  360.     SelectObject(Inst.hMemoryDC, hOldBitmap);
  361. }
  362. #endif
  363.  
  364.  
  365. static
  366. int        mswinext_draw(int x, int y)
  367. {
  368.     HDC    hDC;
  369.     HPEN    hPen,
  370.         hOldPen;
  371.     HBITMAP    hOldBitmap;
  372.     RECT    r;
  373.  
  374.     if (nCurrentInstance == NO_INSTANCE) return -1;
  375.  
  376.     hOldBitmap = SelectObject(Inst.hMemoryDC, Inst.hBitmap);
  377.     hPen = CreatePen(PS_SOLID, Inst.nLWidth, Inst.carray[Inst.nCurColour]);
  378.     if (hPen) {
  379.         hOldPen = SelectObject(Inst.hMemoryDC, hPen);
  380.         MoveTo(Inst.hMemoryDC, r.left = vdevice.cpVx, r.top = vdevice.sizeSy - vdevice.cpVy);
  381.         LineTo(Inst.hMemoryDC, r.right = x, r.bottom = vdevice.sizeSy - y);
  382.         if (Inst.bUseFrontBuf) {
  383.             if (r.top > r.bottom) swap(&(r.top), &(r.bottom));
  384.             if (r.left > r.right) swap(&(r.left), &(r.right));
  385.             hDC = GetDC(Inst.hWinder);
  386.             BitBlt(hDC,
  387.                 r.left, r.top,
  388.                 r.right - r.left + 1,
  389.                 r.bottom - r.top + 1,
  390.                 Inst.hMemoryDC,
  391.                 r.left, r.top,
  392.                 SRCCOPY);
  393.             ReleaseDC(Inst.hWinder, hDC);
  394.             }
  395.         else {
  396.             /* invalidate the region in front buffer */
  397.             mswinext_invalidate_rect(&r);
  398.             }
  399.         SelectObject(Inst.hMemoryDC, hOldPen);
  400.         DeleteObject(hPen);
  401.         }
  402.     hOldBitmap = SelectObject(Inst.hMemoryDC, hOldBitmap);
  403. }
  404.  
  405.  
  406.  
  407. static
  408. int        mswinext_fill(int n, int *x, int *y)
  409. {
  410.     HDC    hDC;
  411.     LPPOINT    lpPoint;
  412.     int    OldPolyMode;
  413.     int    i;
  414.     HBRUSH    hBrush,
  415.         hOldBrush;
  416.     HBITMAP    hOldBitmap;
  417.     RECT    r;
  418.  
  419.     if (nCurrentInstance == NO_INSTANCE) return -1;
  420.  
  421.     hOldBitmap = SelectObject(Inst.hMemoryDC, Inst.hBitmap);
  422.  
  423.     if (lpPoint = (LPPOINT) malloc(sizeof(POINT) * n)) {
  424.          hBrush = CreateSolidBrush(Inst.carray[Inst.nCurColour]);
  425.         if (hBrush) {
  426.             r.left = r.right = x[0];
  427.             r.top = r.bottom = y[0];
  428.             for (i = 0; i < n; i++) {
  429.                 lpPoint[i].x = x[i];
  430.                 if (lpPoint[i].x < r.left) r.left = lpPoint[i].x;
  431.                 else if (lpPoint[i].x > r.right) r.right = lpPoint[i].x;
  432.  
  433.                 lpPoint[i].y = vdevice.sizeSy - y[i];
  434.                 if (lpPoint[i].y < r.top) r.top = lpPoint[i].y;
  435.                 else if (lpPoint[i].y > r.bottom) r.bottom = lpPoint[i].y;
  436.                 }
  437.             hOldBrush = SelectObject(Inst.hMemoryDC, hBrush);
  438.             OldPolyMode = GetPolyFillMode(Inst.hMemoryDC);
  439.             SetPolyFillMode(Inst.hMemoryDC, WINDING);
  440.             Polygon(Inst.hMemoryDC, lpPoint, n);
  441.             if (Inst.bUseFrontBuf) {
  442.                 hDC = GetDC(Inst.hWinder);
  443.                 BitBlt(hDC,
  444.                     r.left, r.top,
  445.                     r.right - r.left + 1,
  446.                     r.bottom - r.top + 1,
  447.                     Inst.hMemoryDC,
  448.                     r.left, r.top,
  449.                     SRCCOPY);
  450.                 ReleaseDC(Inst.hWinder, hDC);
  451.                 }
  452.             else {
  453.                 /* invalidate the region in front buffer */
  454.                 mswinext_invalidate_rect(&r);
  455.                 }
  456.  
  457.             SetPolyFillMode(Inst.hMemoryDC, OldPolyMode);
  458.             SelectObject(Inst.hMemoryDC, hOldBrush);
  459.             DeleteObject(hBrush);
  460.             }
  461.         free(lpPoint);
  462.         }
  463.     hOldBitmap = SelectObject(Inst.hMemoryDC, hOldBitmap);
  464.  
  465.     vdevice.cpVx = x[n-1];
  466.     vdevice.cpVy = y[n-1];
  467. }
  468.  
  469.  
  470.  
  471. static
  472. int        mswinext_color(int i)
  473. {
  474.     if (nCurrentInstance == NO_INSTANCE) return -1;
  475.  
  476.     Inst.nCurColour = (unsigned)i;
  477. }
  478.  
  479.  
  480.  
  481. static
  482. int        mswinext_mapcolor(int i, int r, int g, int b)
  483. {
  484.     if (nCurrentInstance == NO_INSTANCE) return -1;
  485.  
  486.     if (i >= CMAPSIZE) return(-1);
  487.  
  488.     Inst.carray[i] = RGB(r, g, b);
  489.  
  490.     return -1;
  491. }
  492.  
  493.  
  494.  
  495. static
  496. int        mswinext_char(char c)
  497. {
  498.     HDC    hDC;        
  499.     char    s[2];
  500.     HBITMAP    hOldBitmap;
  501.     RECT    r;
  502.     int    OldBkMode;
  503.     DWORD    OldTextColour;
  504.  
  505.     if (nCurrentInstance == NO_INSTANCE) return -1;
  506.  
  507.     hOldBitmap = SelectObject(Inst.hMemoryDC, Inst.hBitmap);
  508.  
  509.     s[0] = c;
  510.     s[1] = '\0';
  511.  
  512.     OldBkMode = SetBkMode(Inst.hMemoryDC, TRANSPARENT);
  513.     OldTextColour = SetTextColor(Inst.hMemoryDC, Inst.carray[Inst.nCurColour]);
  514.     TextOut(Inst.hMemoryDC, r.left = vdevice.cpVx, r.top = vdevice.sizeSy - vdevice.cpVy, s, 1);
  515.     SetTextColor(Inst.hMemoryDC, OldTextColour);
  516.     SetBkMode(Inst.hMemoryDC, OldBkMode);
  517.  
  518.     if (Inst.bUseFrontBuf) {
  519.         hDC = GetDC(Inst.hWinder);
  520.         BitBlt(hDC,
  521.             r.left, r.top,
  522.             Inst.xChar,
  523.             Inst.yChar,
  524.             Inst.hMemoryDC,
  525.             r.left, r.top,
  526.             SRCCOPY);
  527.         ReleaseDC(Inst.hWinder, hDC);
  528.         }
  529.     else {
  530.         /* invalidate the region in front buffer */
  531.         r.right = r.left + Inst.xChar;
  532.         r.bottom = r.top + Inst.yChar;
  533.         mswinext_invalidate_rect(&r);
  534.         }
  535.  
  536.     hOldBitmap = SelectObject(Inst.hMemoryDC, hOldBitmap);
  537. }
  538.  
  539.  
  540.  
  541. static
  542. int        mswinext_string(char *s)
  543. {
  544.     HDC    hDC;
  545.     HBITMAP    hOldBitmap;
  546.     RECT    r;
  547.     int    n;
  548.     int    OldBkMode;
  549.     DWORD    OldTextColour;
  550.  
  551.     if (nCurrentInstance == NO_INSTANCE) return -1;
  552.  
  553.     hOldBitmap = SelectObject(Inst.hMemoryDC, Inst.hBitmap);
  554.  
  555.     OldBkMode = SetBkMode(Inst.hMemoryDC, TRANSPARENT);
  556.     OldTextColour = SetTextColor(Inst.hMemoryDC, Inst.carray[Inst.nCurColour]);
  557.     TextOut(Inst.hMemoryDC, r.left = vdevice.cpVx, r.top = vdevice.sizeSy - vdevice.cpVy, s, n = strlen(s));
  558.     SetTextColor(Inst.hMemoryDC, OldTextColour);
  559.     SetBkMode(Inst.hMemoryDC, OldBkMode);
  560.     if (Inst.bUseFrontBuf) {
  561.         hDC = GetDC(Inst.hWinder);
  562.         BitBlt(hDC,
  563.             r.left, r.top,
  564.             n * Inst.xChar,
  565.             Inst.yChar,
  566.             Inst.hMemoryDC,
  567.             r.left, r.top,
  568.             SRCCOPY);
  569.         ReleaseDC(Inst.hWinder, hDC);
  570.         }
  571.     else {
  572.         /* invalidate the region in front buffer */
  573.         r.right = r.left + n * Inst.xChar;
  574.         r.bottom = r.top + Inst.yChar;
  575.         mswinext_invalidate_rect(&r);
  576.         }
  577.  
  578.     hOldBitmap = SelectObject(Inst.hMemoryDC, hOldBitmap);
  579. }
  580.  
  581.  
  582.  
  583. static
  584. int        mswinext_font(char *font)
  585. {
  586.     if (nCurrentInstance == NO_INSTANCE) return -1;
  587.  
  588.     /* NOT IMPLEMENTED */
  589.     return 1;
  590. }
  591.  
  592.  
  593.  
  594. static
  595. int        mswinext_frontbuf()
  596. {
  597.     if (nCurrentInstance == NO_INSTANCE) return -1;
  598.  
  599.     Inst.bUseFrontBuf = TRUE;
  600. }
  601.  
  602.  
  603.  
  604. static
  605. int        mswinext_backbuf()
  606. {
  607.     if (nCurrentInstance == NO_INSTANCE) return -1;
  608.  
  609.     Inst.bUseFrontBuf = FALSE;
  610.     Inst.BackRect.left = Inst.BackRect.top = 32765;
  611.     Inst.BackRect.right = Inst.BackRect.bottom = -32765;
  612.     return 1;
  613. }
  614.  
  615.  
  616.  
  617. static
  618. int        mswinext_swapbuf()
  619. {
  620.     HDC    hDC;
  621.     RECT    r;
  622.     HBITMAP    hOldBitmap;
  623.  
  624.     if (nCurrentInstance == NO_INSTANCE) return -1;
  625.  
  626.     hDC = GetDC(Inst.hWinder);
  627.     hOldBitmap = SelectObject(Inst.hMemoryDC, Inst.hBitmap);
  628.     BitBlt(hDC,
  629.         Inst.BackRect.left, Inst.BackRect.top,
  630.         Inst.BackRect.right - Inst.BackRect.left,
  631.         Inst.BackRect.bottom - Inst.BackRect.top,
  632.         Inst.hMemoryDC,
  633.         Inst.BackRect.left, Inst.BackRect.top,
  634.         SRCCOPY);
  635.     Inst.BackRect.left = Inst.BackRect.top = 32765;
  636.     Inst.BackRect.right = Inst.BackRect.bottom = -32765;
  637.  
  638.     ReleaseDC(Inst.hWinder, hDC);
  639.     SelectObject(Inst.hMemoryDC, hOldBitmap);
  640. }
  641.  
  642.  
  643. int        mswin_verror(char *msg)
  644. {
  645.     MessageBox(NULL, (LPSTR)msg, "A VOGLE error has occurred!", MB_APPLMODAL | MB_ICONEXCLAMATION |  MB_OK);
  646. }
  647.  
  648.  
  649.  
  650. static
  651. int        mswinext_setlw(int w)
  652. {
  653.     if (nCurrentInstance == NO_INSTANCE) return -1;
  654.  
  655.     if (w == 0) Inst.nLWidth = 1;
  656.     else Inst.nLWidth = 3;
  657. }
  658.  
  659.  
  660. /*
  661.  * Does nothing....
  662.  */
  663. static
  664. noop()
  665. {
  666.     return(-1);
  667. }
  668.  
  669.  
  670. /*
  671.  * the device entry
  672.  */
  673. static DevEntry mswinextdev = {
  674.     "mswinext",
  675.     "large",
  676.     "small",
  677.     mswinext_backbuf,
  678.     mswinext_char,
  679.     noop,
  680.     mswinext_clear,
  681.     mswinext_color,
  682.     mswinext_draw,
  683.     mswinext_exit,
  684.     mswinext_fill,
  685.     mswinext_font,
  686.     mswinext_frontbuf,
  687.     noop,
  688.     mswinext_init,
  689.     noop,
  690.     mswinext_mapcolor,
  691.     mswinext_setlw,
  692.     mswinext_string,
  693.     mswinext_swapbuf,
  694.     noop
  695. };
  696.  
  697. /*
  698.  * _mswinext_devcpy
  699.  *
  700.  *    copy the mswinext device into vdevice.dev.
  701.  */
  702. int        _mswinext_devcpy()
  703. {
  704.     vdevice.dev = mswinextdev;
  705. }
  706.  
  707.  
  708. /*
  709.  * Setup the window info for current instance.
  710.  */
  711. static
  712. int        mswinext_SetupInstance(HWND hWnd, int w, int h)
  713. {
  714.     HDC        hDC;
  715.     RECT        r;
  716.     TEXTMETRIC    tm;
  717.     HBRUSH        hBrush,
  718.             hOldBrush;
  719.     HBITMAP        hOldBitmap;
  720.  
  721.     /*  assign the window */
  722.     Inst.hWinder = hWnd;
  723.  
  724.     /*
  725.      * Let VOGLE know about the dimensions of the window to be used.
  726.      * Make it square.
  727.      */
  728.     r.top = r.left = 0;
  729.     r.right = w; r.bottom = h;
  730.     vdevice.sizeX = vdevice.sizeY = min(r.bottom, r.right);
  731.     vdevice.sizeSx = r.right;
  732.     vdevice.sizeSy = r.bottom;
  733.  
  734.     /* determine size of default window font */
  735.     hDC = GetDC(Inst.hWinder);
  736.     GetTextMetrics(hDC, &tm);
  737.     Inst.xChar = tm.tmMaxCharWidth;
  738.     Inst.yChar = tm.tmHeight + tm.tmExternalLeading;
  739.  
  740.     /*  zap previous DC/bitmap */
  741.     mswinext_cleanup();
  742.  
  743.     /* create a bitmap and memory context compatible with Inst.hWinder */
  744.     Inst.hMemoryDC = CreateCompatibleDC(hDC);
  745.     Inst.hBitmap = CreateCompatibleBitmap(hDC, vdevice.sizeSx, vdevice.sizeSy);
  746.  
  747.     /* clear the bitmap */
  748.     hOldBitmap = SelectObject(Inst.hMemoryDC, Inst.hBitmap);
  749.     hBrush = GetStockObject(BLACK_BRUSH);
  750.     if (hBrush) {
  751.         hOldBrush = SelectObject(Inst.hMemoryDC, hBrush);
  752.         r.top = r.left = 0;
  753.         r.right = vdevice.sizeSx;
  754.         r.bottom = vdevice.sizeSy;
  755.         FillRect(Inst.hMemoryDC, &r, hBrush);
  756.         SelectObject(Inst.hMemoryDC, hOldBrush);
  757.         }
  758.     SelectObject(Inst.hMemoryDC, hOldBitmap);
  759.  
  760.     ReleaseDC(Inst.hWinder, hDC);
  761.  
  762.     /* good return */
  763.     return TRUE;
  764. }
  765.  
  766.  
  767.  
  768. /*
  769.  * vo_mswinext_window
  770.  *
  771.  *    Assigns VOGL/VOGLE a window to use.
  772.  *    You MUST use this routine before (and directly before)
  773.  *    calling vinit().
  774.  */
  775. int    vo_mswinext_window(HWND hWnd, int w, int h)
  776. {
  777.     /* store window info until vinit() calls mswinext_init() */
  778.     DeferInfo.hWnd = hWnd;
  779.     DeferInfo.w = w;
  780.     DeferInfo.h = h;
  781.  
  782.     return TRUE;
  783. }
  784.  
  785.  
  786.  
  787. /*
  788.  *    vo_mswinext_win_size
  789.  *
  790.  * If the user has resized the window, then
  791.  * you might wish to call this routine to tell VOGL/VOGLE about it.
  792.  */
  793. int    vo_mswinext_win_size(int w, int h)
  794. {
  795.     mswinext_SetupInstance(Inst.hWinder, w, h);
  796.  
  797.     return TRUE;
  798. }
  799.  
  800.  
  801. /****
  802.  * Paint the client area of a (the) VOGL/VOGLE window.
  803.  * This should be called by the window's window procedure
  804.  * in response to a WM_PAINT message ONLY!
  805.  **/
  806. int    vo_mswinext_paint_window(HWND hWnd)
  807. {
  808.     PAINTSTRUCT    ps;
  809.     HDC        hDC;
  810.     HBITMAP        hOldBitmap;
  811.  
  812.     if (nCurrentInstance == NO_INSTANCE) return 0;
  813.  
  814.     if (hWnd) {
  815.         BeginPaint(hWnd, &ps);
  816.         hOldBitmap = SelectObject(Inst.hMemoryDC, Inst.hBitmap);
  817.         hDC = GetDC(hWnd);
  818.         BitBlt(hDC,
  819.             ps.rcPaint.left, ps.rcPaint.top,
  820.             ps.rcPaint.right - ps.rcPaint.left,
  821.             ps.rcPaint.bottom - ps.rcPaint.top,
  822.             Inst.hMemoryDC,
  823.             ps.rcPaint.left, ps.rcPaint.top,
  824.             SRCCOPY);
  825.         SelectObject(Inst.hMemoryDC, hOldBitmap);
  826.         ReleaseDC(hWnd, hDC);
  827.         EndPaint(hWnd, &ps);
  828.         }
  829.  
  830.     return TRUE;
  831. }
  832.  
  833.  
  834. /****
  835.  * Paint the client area of a (the) VOGL/VOGLE window to
  836.  * a given device context.
  837.  * This should be called by the window's window procedure
  838.  * in response to a WM_PAINT message ONLY!
  839.  **/
  840. int    vo_mswinext_paint_dc(HDC hDC)
  841. {
  842.     RECT    rClip;
  843.     HBITMAP    hOldBitmap;
  844.  
  845.     if (nCurrentInstance == NO_INSTANCE) return 0;
  846.  
  847.     if (Inst.hBitmap && Inst.hMemoryDC) {
  848.         hOldBitmap = SelectObject(Inst.hMemoryDC, Inst.hBitmap);
  849.         GetClipBox(hDC, &rClip);
  850.         BitBlt(hDC,
  851.             rClip.left, rClip.top,
  852.             rClip.right - rClip.left,
  853.             rClip.bottom - rClip.top,
  854.             Inst.hMemoryDC,
  855.             rClip.left, rClip.top,
  856.             SRCCOPY);
  857.         SelectObject(Inst.hMemoryDC, hOldBitmap);
  858.         }
  859.  
  860.     return TRUE;
  861. }
  862.  
  863.  
  864.  
  865. static
  866. void    swap(int *a, int *b)
  867. {
  868.     int    t;
  869.  
  870.     t = *a;
  871.     *a = *b;
  872.     *b = t;
  873. }
  874.  
  875.