home *** CD-ROM | disk | FTP | other *** search
/ gondwana.ecr.mu.oz.au/pub/ / Graphics.tar / Graphics / VOGLE.ZIP / VOGLE / DRIVERS / IBMPC / MSWIN.C < prev    next >
C/C++ Source or Header  |  2000-02-11  |  27KB  |  1,034 lines

  1. /****************************************************************************
  2.  
  3.     PROGRAM: MSWIN.C
  4.  
  5.     PURPOSE: MS-Windows driver for VOGLE/VOGL
  6.  
  7.     FUNCTIONS:
  8.  
  9.     WinMain() - calls initialization function, calls user's VOGLE program (main)
  10.     InitApplication() - initializes window data and registers window
  11.     InitInstance() - saves instance handle
  12.     MainWndProc() - processes messages
  13.     About() - processes messages for "About" dialog box
  14.     mswin_msg_loop() - grabs and dispatches windows messages (until no more pending)
  15.     mswin_cleanup() - frees objects created along the way in preparation for exit
  16.     mswin_...() - VOGLE driver routines called by VOGLE
  17.     swap(() - swaps two integer values
  18.  
  19.     COMMENTS:
  20.  
  21.     The GENERIC sample program from Windows SDK was used as the basis
  22.     for this driver.
  23.  
  24. ****************************************************************************/
  25.  
  26. #include "windows.h"                /* required for all Windows applications */
  27. #include <stdio.h>
  28. #include "mswin.h"                /* specific to this program */
  29. #include "vogle.h"
  30.  
  31. #define    CMAPSIZE    256            /* max size of colour map */
  32. #define    WM_VOGLE    WM_USER            /* VOGLE's own window message */
  33. #define    WM_VOGLE_ERROR    WM_USER + 1        /* VOGLE's ERROR window message */
  34.  
  35. static    HANDLE        hInst;            /* current instance */
  36. static    HWND        hWinder;        /* handle of VOGLE's window */
  37. static    HDC        hMemoryDC;        /* memory device context of hWinder */
  38. static    HBITMAP        hBitmap = (HBITMAP) 0;    /* bitmap compatible with hWinder's */
  39.  
  40. static    int        CmdShow;        /* TRUE if window to be shown on start-up */
  41. static    unsigned int    cur_color = 1;        /* index of current colour in carray */
  42. static    COLORREF    carray[CMAPSIZE];    /* list of known colour values */
  43. static    int        use_front_buf = TRUE;    /* FALSE if double buffering */
  44. static    int        vogle_active = TRUE;    /* FALSE when app has been made inactive (iconized) */
  45. static    int        have_mouse = FALSE;    /* TRUE if we have a mouse on our PC - errggh! */
  46. static    int        xMouse = 0;        /* last known mouse position */
  47. static    int        yMouse = 0;
  48. static    int        LButton = 0,        /* mouse button states: 1 == down */
  49.             MButton = 0,
  50.             RButton = 0;
  51. static    int        sizeX = 0;        /* width of VOGLE window */
  52. static    int        sizeY = 0;        /* height of VOGLE window */
  53. static    short int    xChar;            /* width of system font character */
  54. static    short int    yChar;            /* height of system font character */
  55. static    char        current_key = 0;    /* current key pressed at keyboard; 0 if no key is being pressed */
  56. static    RECT        BackRect;        /* bitmap area to be swapped on next mswin_swapbuf() call */
  57. static    int        argc;            /* command line argument count found by us */
  58. static    char        **argv;            /* command line argument list built by us */
  59.  
  60. static int        lwidth = 1;
  61.  
  62. static    void        mswin_invalidate_rect(LPRECT);
  63. static    void        mswin_cleanup();
  64. static    void        swap(int *, int *);
  65. char            *strdup(char *);
  66.  
  67. int PASCAL        WinMain(HANDLE, HANDLE, LPSTR, int);
  68. BOOL            InitApplication(HANDLE);
  69. BOOL            InitInstance(HANDLE, int);
  70. long FAR PASCAL        MainWndProc(HWND, unsigned, WORD, LONG);
  71. BOOL FAR PASCAL        About(HWND, unsigned, WORD, LONG);
  72.  
  73. /*
  74.  * Does nothing....
  75.  */
  76. static
  77. noop()
  78. {
  79.     return(-1);
  80. }
  81.  
  82. /****************************************************************************
  83.  
  84.     FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
  85.  
  86.     PURPOSE: calls initialization function, calls user's VOGLE program (main)
  87.  
  88.     COMMENTS:
  89.  
  90.         Windows recognizes this function by name as the initial entry point 
  91.         for the program.  This function calls the application initialization 
  92.         routine, if no other instance of the program is running, and always 
  93.         calls the instance initialization routine.  After breaking the command
  94.     line passed from Windows, it executes the routine main(). This is a
  95.     standard looking main program. It should call vinit() as soon as
  96.     possible so that the program's window can be shown. When main
  97.     terminates, a QUIT message is posted that starts the termination
  98.     of the program. The program terminates in mswin_msg_loop.
  99.  
  100.         If this function must abort before entering the message loop, it 
  101.         returns the conventional value NULL.  
  102.  
  103. ****************************************************************************/
  104.  
  105. int PASCAL    WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
  106. HANDLE    hInstance;                /* current instance         */
  107. HANDLE    hPrevInstance;                /* previous instance         */
  108. LPSTR    lpCmdLine;                /* command line             */
  109. int    nCmdShow;                /* show-window type (open/icon) */
  110. {
  111.     int    i;
  112.     LPSTR    p;
  113.     char    v[100];
  114.  
  115.     if (!hPrevInstance)            /* Other instances of app running? */
  116.         if (!InitApplication(hInstance))/* Initialize shared things */
  117.             return (FALSE);        /* Exits if unable to initialize     */
  118.  
  119.     /* Perform initializations that apply to a specific instance */
  120.     if (!InitInstance(hInstance, nCmdShow))
  121.         return (FALSE);
  122.  
  123.     /* setup command line arguments argc, argv */
  124.     argc = 0;
  125.     p = lpCmdLine;
  126.     if (p) {
  127.         while (*p) {
  128.             while (*p == ' ') p++;
  129.             if (!*p) break;
  130.             argc++;
  131.             while ((*p != ' ') && (*p != '\0')) p++;
  132.             }
  133.         }
  134.  
  135.     argv = (char **)calloc(argc+1, sizeof(char *));
  136.     if (argv) {
  137.         argv[0] = strdup("vogle");
  138.         argc = 1;
  139.         p = lpCmdLine;
  140.         while (*p) {
  141.             while (*p == ' ') p++;
  142.             if (!*p) break;
  143.             i = 0;
  144.             while ((*p != ' ') && (*p != '\0')) v[i++] = *(p++);
  145.             v[i] = *p;
  146.             argv[argc++] = strdup(v);
  147.             }
  148.         }
  149.     else argc = 0;
  150.  
  151.     /* call user's program - it should call vinit() as soon as possible */
  152.     main(argc, argv);
  153.  
  154.     /* we're done */
  155.     PostQuitMessage(0);
  156.  
  157.     /* user's program has finished - clean up the outstanding messages */
  158.     return (mswin_msg_loop());
  159. }
  160.  
  161.  
  162.  
  163. /****************************************************************************
  164.  
  165.     FUNCTION: InitApplication(HANDLE)
  166.  
  167.     PURPOSE: Initializes window data and registers window class
  168.  
  169.     COMMENTS:
  170.  
  171.         This function is called at initialization time only if no other 
  172.         instances of the application are running.  This function performs 
  173.         initialization tasks that can be done once for any number of running 
  174.         instances.  
  175.  
  176.         In this case, we initialize a window class by filling out a data 
  177.         structure of type WNDCLASS and calling the Windows RegisterClass() 
  178.         function.  Since all instances of this application use the same window 
  179.         class, we only need to do this when the first instance is initialized.  
  180.  
  181.  
  182. ****************************************************************************/
  183.  
  184. BOOL    InitApplication(hInstance)
  185. HANDLE    hInstance;                /* current instance         */
  186. {
  187.     WNDCLASS    wc;
  188.  
  189.     /* Fill in window class structure with parameters that describe the       */
  190.     /* main window.                                                           */
  191.  
  192.     wc.style = NULL;            /* Class style(s).                    */
  193.     wc.lpfnWndProc = MainWndProc;        /* Function to retrieve messages for  */
  194.                         /* windows of this class.             */
  195.     wc.cbClsExtra = 0;            /* No per-class extra data.           */
  196.     wc.cbWndExtra = 0;            /* No per-window extra data.          */
  197.     wc.hInstance = hInstance;        /* Application that owns the class.   */
  198.     wc.hIcon = LoadIcon(hInstance, "VOGLEICON");
  199.     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  200.     wc.hbrBackground = GetStockObject(BLACK_BRUSH); 
  201.     wc.lpszMenuName =  "VogleMenu";        /* Name of menu resource in .RC file. */
  202.     wc.lpszClassName = "VogleWClass";    /* Name used in call to CreateWindow. */
  203.  
  204.     /* Register the window class and return success/failure code. */
  205.     return (RegisterClass(&wc));
  206. }
  207.  
  208.  
  209.  
  210. /****************************************************************************
  211.  
  212.     FUNCTION:  InitInstance(HANDLE, int)
  213.  
  214.     PURPOSE:  Saves instance handle and creates main window
  215.  
  216.     COMMENTS:
  217.  
  218.         This function is called at initialization time for every instance of 
  219.         this application.  This function performs initialization tasks that 
  220.         cannot be shared by multiple instances.  
  221.  
  222.         In this case, we save the instance handle in a static variable and 
  223.         create and display the main program window.  
  224.         
  225. ****************************************************************************/
  226.  
  227. BOOL    InitInstance(hInstance, nCmdShow)
  228. HANDLE    hInstance;                /* Current instance identifier.       */
  229. int    nCmdShow;                /* Param for first ShowWindow() call. */
  230. {
  231.     /* Save the instance handle in static variable, which will be used in  */
  232.     /* many subsequent calls from this application to Windows.            */
  233.     /* Also save the handle of the main window - hWinder */
  234.  
  235.     hInst = hInstance;
  236.     CmdShow = nCmdShow;
  237.  
  238.     return (TRUE);
  239. }
  240.  
  241.  
  242. /****************************************************************************
  243.  
  244.     FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
  245.  
  246.     PURPOSE:  Processes messages
  247.  
  248.     MESSAGES:
  249.  
  250.     WM_PAINT    - copy bit image from back buffer to front buffer
  251.     WM_MOUSEMOVE    - track position of mouse as it moves over window
  252.     WM_LBUTTONDOWN    - track state of mouse button
  253.     WM_LBUTTONUP    - track state of mouse button
  254.     WM_MBUTTONDOWN    - track state of mouse button
  255.     WM_MBUTTONUP    - track state of mouse button
  256.     WM_RBUTTONDOWN    - track state of mouse button
  257.     WM_RBUTTONUP    - track state of mouse button
  258.     WM_CHAR        - track last key pressed on keyboard
  259.     WM_KEYUP    - track last key pressed on keyboard
  260.     WM_ACTIVATE    - track active state of this application
  261.     WM_COMMAND    - application menu (About dialog box)
  262.     WM_DESTROY    - destroy window
  263.  
  264.     COMMENTS:
  265.  
  266.     To process the IDM_ABOUT message, call MakeProcInstance() to get the
  267.     current instance address of the About() function.  Then call Dialog
  268.     box which will create the box according to the information in your
  269.     Vogle.rc file and turn control over to the About() function.    When
  270.     it returns, free the intance address.
  271.  
  272. ****************************************************************************/
  273.  
  274. long FAR PASCAL MainWndProc(hWnd, message, wParam, lParam)
  275. HWND    hWnd;                    /* window handle             */
  276. unsigned message;                /* type of message             */
  277. WORD    wParam;                    /* additional information         */
  278. LONG    lParam;                    /* additional information         */
  279. {
  280.     HDC        hDC;
  281.     HBITMAP        hOldBitmap;
  282.     PAINTSTRUCT    ps;
  283.  
  284.     FARPROC lpProcAbout;            /* pointer to the "About" function */
  285.  
  286.     switch (message) {
  287.  
  288.         case WM_PAINT :
  289.             if (!hBitmap) {
  290.                 /* no back buffer yet - let's use default procedure */
  291.                 return (DefWindowProc(hWnd, message, wParam, lParam));
  292.                 }
  293.             BeginPaint(hWnd, &ps);
  294.             hOldBitmap = SelectObject(hMemoryDC, hBitmap);
  295.             hDC = GetDC(hWinder);
  296.             BitBlt(hDC,
  297.                 ps.rcPaint.left, ps.rcPaint.top,
  298.                 ps.rcPaint.right - ps.rcPaint.left,
  299.                 ps.rcPaint.bottom - ps.rcPaint.top,
  300.                 hMemoryDC,
  301.                 ps.rcPaint.left, ps.rcPaint.top,
  302.                 SRCCOPY);
  303.             SelectObject(hMemoryDC, hOldBitmap);
  304.             ReleaseDC(hWnd, hDC);
  305.             EndPaint(hWnd, &ps);
  306.             break;
  307.  
  308.         case WM_MOUSEMOVE :
  309.             xMouse = LOWORD(lParam);
  310.             yMouse = HIWORD(lParam);
  311.             break;
  312.  
  313.         case WM_LBUTTONDOWN :    LButton = 1; break;
  314.         case WM_LBUTTONUP :    LButton = 0; break;
  315.         case WM_MBUTTONDOWN :    MButton = 1; break;
  316.         case WM_MBUTTONUP :    MButton = 0; break;
  317.         case WM_RBUTTONDOWN :    RButton = 1; break;
  318.         case WM_RBUTTONUP :    RButton = 0; break;
  319.  
  320.         case WM_CHAR:
  321.             /* user has pressed a character - save it for mswin_checkkey() */
  322.             current_key = wParam;
  323.             break;
  324.  
  325.         case WM_KEYUP:
  326.             /* user has released a key - if it is a meta-key (SHIFT, CTRL) ignore it */
  327.             /* otherwise we assume that the key released was the one that generated  */
  328.             /* the WM_CHAR message and we reset current_key. This assumption is      */
  329.             /* probably VERY wrong!                                                  */
  330.             switch (wParam) {
  331.                 case VK_SHIFT :
  332.                 case VK_CONTROL :
  333.                 case VK_MENU :
  334.                 case VK_CAPITAL :
  335.                 case VK_NUMLOCK :
  336.                     break;
  337.                 default : current_key = 0;
  338.                 }
  339.             break;
  340.  
  341.         case WM_ACTIVATE :
  342.             vogle_active = !IsIconic(hWnd);
  343.             break;
  344.  
  345.         case WM_VOGLE_ERROR :
  346.             /* VOGLE error occurred - display error message in a window, then QUIT */
  347.             MessageBox(hWinder, (LPSTR)lParam, "A VOGLE error has occurred!", MB_APPLMODAL | MB_ICONEXCLAMATION |  MB_OK);
  348.             PostMessage(hWinder, WM_DESTROY, NULL, NULL);
  349.             break;
  350.  
  351.         case WM_COMMAND :       /* message: command from application menu */
  352.             if (wParam == IDM_ABOUT) {
  353.                 lpProcAbout = MakeProcInstance(About, hInst);
  354.                 DialogBox(hInst,    /* current instance         */
  355.                     "AboutBox",    /* resource to use         */
  356.                     hWnd,        /* parent handle         */
  357.                     lpProcAbout);    /* About() instance address */
  358.                 FreeProcInstance(lpProcAbout);
  359.                 }
  360.             else return (DefWindowProc(hWnd, message, wParam, lParam));
  361.             break;
  362.  
  363.         case WM_DESTROY :            /* message: window being destroyed */
  364.                 PostQuitMessage(0);
  365.                 break;
  366.  
  367.         default :                /* Passes it on if unproccessed    */
  368.                 return (DefWindowProc(hWnd, message, wParam, lParam));
  369.         }
  370.     return (NULL);
  371. }
  372.  
  373.  
  374. /****************************************************************************
  375.  
  376.     FUNCTION: About(HWND, unsigned, WORD, LONG)
  377.  
  378.     PURPOSE:  Processes messages for "About" dialog box
  379.  
  380.     MESSAGES:
  381.  
  382.     WM_INITDIALOG - initialize dialog box
  383.     WM_COMMAND    - Input received
  384.  
  385.     COMMENTS:
  386.  
  387.     No initialization is needed for this particular dialog box, but TRUE
  388.     must be returned to Windows.
  389.  
  390.     Wait for user to click on "Ok" button, then close the dialog box.
  391.  
  392. ****************************************************************************/
  393.  
  394. BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
  395. HWND    hDlg;                    /* window handle of the dialog box */
  396. unsigned message;                /* type of message                 */
  397. WORD    wParam;                    /* message-specific information    */
  398. LONG    lParam;
  399. {
  400.     switch (message) {
  401.         case WM_INITDIALOG:        /* message: initialize dialog box */
  402.             return (TRUE);
  403.  
  404.         case WM_COMMAND:        /* message: received a command */
  405.             if (wParam == IDOK ||    /* "OK" box selected?         */
  406.                 wParam == IDCANCEL) {    /* System menu close command? */
  407.                 EndDialog(hDlg, TRUE);    /* Exits the dialog box         */
  408.                 return (TRUE);
  409.                 }
  410.         break;
  411.         }
  412.     return (FALSE);                /* Didn't process a message    */
  413. }
  414.  
  415.  
  416.  
  417. /****************************************************************************
  418.     VOGLE bits
  419. ****************************************************************************/
  420.  
  421. static
  422. int        mswin_msg_loop()
  423. {
  424.     MSG    msg;
  425.  
  426.     /* put our own message in the message queue */
  427.     PostMessage(hWinder, WM_VOGLE, NULL, NULL);
  428.  
  429.     while (GetMessage(&msg, NULL, NULL, NULL) || !vogle_active) {
  430.         TranslateMessage(&msg);       /* Translates virtual key codes         */
  431.         DispatchMessage(&msg);       /* Dispatches message to window         */
  432.         if (msg.message == WM_VOGLE) break;
  433.         }
  434.  
  435.     if (msg.message == WM_QUIT) {
  436.         mswin_cleanup();
  437.         exit(msg.wParam);
  438.         }
  439.     return (msg.wParam);
  440. }
  441.  
  442.  
  443.  
  444. static
  445. void        mswin_cleanup()
  446. {
  447.     int    i;
  448.  
  449.     DeleteObject(hBitmap);
  450.     DeleteDC(hMemoryDC);
  451.     for (i = 0; i < argc; i++) free(argv[i]);
  452.     free(argv);
  453. }
  454.  
  455.  
  456.  
  457. static
  458. void        mswin_invalidate_rect(r)
  459.     LPRECT    r;
  460. {
  461.     if (r->left < BackRect.left) BackRect.left = r->left;
  462.     if (r->right > BackRect.right) BackRect.right = r->right;
  463.     if (r->top < BackRect.top) BackRect.top = r->top;
  464.     if (r->bottom > BackRect.bottom) BackRect.bottom = r->bottom;
  465. }
  466.  
  467.  
  468.  
  469. int        mswin_init()
  470. {
  471.     RECT    rect;
  472.     HDC    hDC;                /* device context of Desktop Window */
  473.     TEXTMETRIC    tm;
  474.     RECT    r;
  475.     HBRUSH    hBrush,
  476.         hOldBrush;
  477.     HBITMAP    hOldBitmap;
  478.     int    prefx, prefy,            /* values for the preferred */
  479.         prefxs, prefys,            /*   window size and position */
  480.         x, y;
  481.  
  482.  
  483.     /* determine a preferred size and position */
  484.     getprefposandsize(&prefx, &prefy, &prefxs, &prefys);
  485.     if (prefx > -1) {
  486.         x = prefx;
  487.         y = prefy;
  488.         }
  489.     else {
  490.         x = y = CW_USEDEFAULT;
  491.         }
  492.  
  493.     if (prefxs > -1) {
  494.         sizeX = prefxs;
  495.         sizeY = prefys;
  496.         }
  497.     else {
  498.         /* figure out a good size based on display device capabilities */
  499.  
  500.         hDC = GetDC(GetDesktopWindow());
  501.         sizeX = sizeY = ((GetDeviceCaps(hDC, HORZRES) * 2) / 3);
  502.         ReleaseDC(GetDesktopWindow(), hDC);
  503.         }
  504.  
  505.  
  506.     /* Create a main window for this application instance */
  507.     hWinder = CreateWindow(
  508.         "VogleWClass",            /* See RegisterClass() call.          */
  509.         "Vogle Application",        /* Text for window title bar.         */
  510.         WS_OVERLAPPEDWINDOW,            /* Window style.                      */
  511.         x,                          /* Default horizontal position.       */
  512.         y,                /* Default vertical position.         */
  513.         sizeX,                /* Default width.                     */
  514.         45 + sizeY,            /* Default height.  + a bit                   */
  515.         NULL,                           /* Overlapped windows have no parent. */
  516.         NULL,                           /* Use the window class menu.         */
  517.         hInst,                          /* This instance owns this window.    */
  518.         NULL                            /* Pointer not needed.                */
  519.         );
  520.  
  521.     /* If window could not be created, return "failure" */
  522.     if (!hWinder) return (FALSE);
  523.     hDC = GetDC(hWinder);
  524.     SetViewportOrg(hDC, 0, 0);
  525.     ShowWindow(hWinder, CmdShow);    /* Show the window                        */
  526.     UpdateWindow(hWinder);          /* Sends WM_PAINT message                 */
  527.  
  528.     mswin_msg_loop();
  529.  
  530.     /*
  531.      *  Let VOGLE know about the dimensions of the window known as hWinder.
  532.      */
  533.  
  534.     hDC = GetDC(GetDesktopWindow());
  535.     vdevice.depth = GetDeviceCaps(hDC, PLANES);
  536.     ReleaseDC(GetDesktopWindow(), hDC);
  537.  
  538.     /* determine size of default (system) font */
  539.     hDC = GetDC(hWinder);
  540.     GetTextMetrics(hDC, &tm);
  541.     xChar = tm.tmMaxCharWidth;
  542.     yChar = tm.tmHeight + tm.tmExternalLeading;
  543.  
  544.     /* set window size - make it square */
  545.     vdevice.sizeX = vdevice.sizeY = min(sizeX, sizeY) - 1;
  546.      vdevice.sizeSx = sizeX - 1;
  547.     vdevice.sizeSy = sizeY - 1;
  548.  
  549.     /* create a bitmap and memory context compatible with hWinder */
  550.     hMemoryDC = CreateCompatibleDC(hDC);
  551.     hBitmap = CreateCompatibleBitmap(hDC, vdevice.sizeSx, vdevice.sizeSy);
  552.  
  553.     /* clear the bitmap */
  554.     hOldBitmap = SelectObject(hMemoryDC, hBitmap);
  555.     hBrush = GetStockObject(BLACK_BRUSH);
  556.     if (hBrush) {
  557.         hOldBrush = SelectObject(hMemoryDC, hBrush);
  558.         r.top = r.left = 0;
  559.         r.right = vdevice.sizeSx;
  560.         r.bottom = vdevice.sizeSy;
  561.         FillRect(hMemoryDC, &r, hBrush);
  562.         SelectObject(hMemoryDC, hOldBrush);
  563.         }
  564.     SelectObject(hMemoryDC, hOldBitmap);
  565.  
  566.     ReleaseDC(hWinder, hDC);
  567.  
  568.     /* set up colour indices */
  569.     carray[0] = RGB(  0,   0,   0);
  570.     carray[1] = RGB(255,   0,   0);
  571.     carray[2] = RGB(  0, 255,   0);
  572.     carray[3] = RGB(255, 255,   0);
  573.     carray[4] = RGB(  0,   0, 255);
  574.     carray[5] = RGB(255,   0, 255);
  575.     carray[6] = RGB(  0, 255, 255);
  576.     carray[7] = RGB(255, 255, 255);
  577.  
  578.     have_mouse = GetSystemMetrics(SM_MOUSEPRESENT);
  579.  
  580.     mswin_msg_loop();
  581.  
  582.     return TRUE;
  583. }
  584.  
  585.  
  586.  
  587. int        mswin_exit()
  588. {
  589.     PostQuitMessage(0);
  590.     mswin_msg_loop();
  591.     return 1;
  592. }
  593.  
  594.  
  595.  
  596. int        mswin_clear()
  597. {
  598.     HDC    hDC;
  599.     RECT    r;
  600.     HBRUSH    hBrush,
  601.         hOldBrush;
  602.     HBITMAP    hOldBitmap;
  603.  
  604.     hOldBitmap = SelectObject(hMemoryDC, hBitmap);
  605.     GetClientRect(hWinder, &r);
  606.     hBrush = CreateSolidBrush(carray[cur_color]);
  607.     if (hBrush) {
  608.         hOldBrush = SelectObject(hMemoryDC, hBrush);
  609.         FillRect(hMemoryDC, &r, hBrush);
  610.         if (use_front_buf) {
  611.             hDC = GetDC(hWinder);
  612.             BitBlt(hDC,
  613.                 r.left, r.top,
  614.                 r.right - r.left,
  615.                 r.bottom - r.top,
  616.                 hMemoryDC,
  617.                 r.left, r.top,
  618.                 SRCCOPY);
  619.             ReleaseDC(hWinder, hDC);
  620.             }
  621.         else {
  622.             /* invalidate the region in front buffer */
  623.             mswin_invalidate_rect(&r);
  624.             }
  625.         SelectObject(hMemoryDC, hOldBrush);
  626.         DeleteObject(hBrush);
  627.         }
  628.     SelectObject(hMemoryDC, hOldBitmap);
  629.  
  630.     mswin_msg_loop();
  631. }
  632.  
  633.  
  634.  
  635. int        mswin_draw(x, y)
  636. int        x, y;
  637. {
  638.     HDC    hDC;
  639.     HPEN    hPen,
  640.         hOldPen;
  641.     HBITMAP    hOldBitmap;
  642.     RECT    r;
  643.  
  644.     hOldBitmap = SelectObject(hMemoryDC, hBitmap);
  645.     hPen = CreatePen(PS_SOLID, lwidth, carray[cur_color]);
  646.     if (hPen) {
  647.         hOldPen = SelectObject(hMemoryDC, hPen);
  648.         MoveTo(hMemoryDC, r.left = vdevice.cpVx, r.top = vdevice.sizeSy - vdevice.cpVy);
  649.         LineTo(hMemoryDC, r.right = x, r.bottom = vdevice.sizeSy - y);
  650.         if (use_front_buf) {
  651.             if (r.top > r.bottom) swap(&(r.top), &(r.bottom));
  652.             if (r.left > r.right) swap(&(r.left), &(r.right));
  653.             hDC = GetDC(hWinder);
  654.             BitBlt(hDC,
  655.                 r.left, r.top,
  656.                 r.right - r.left + 1,
  657.                 r.bottom - r.top + 1,
  658.                 hMemoryDC,
  659.                 r.left, r.top,
  660.                 SRCCOPY);
  661.             ReleaseDC(hWinder, hDC);
  662.             }
  663.         else {
  664.             /* invalidate the region in front buffer */
  665.             mswin_invalidate_rect(&r);
  666.             }
  667.         SelectObject(hMemoryDC, hOldPen);
  668.         DeleteObject(hPen);
  669.         }
  670.     hOldBitmap = SelectObject(hMemoryDC, hOldBitmap);
  671.  
  672.     mswin_msg_loop();
  673. }
  674.  
  675.  
  676.  
  677. int        mswin_fill(n, x, y)
  678. int        n;
  679. int        *x, *y;
  680. {
  681.     HDC    hDC;
  682.     LPPOINT    lpPoint;
  683.     int    OldPolyMode;
  684.     int    i;
  685.     HBRUSH    hBrush,
  686.         hOldBrush;
  687.     HBITMAP    hOldBitmap;
  688.     RECT    r;
  689.  
  690.     hOldBitmap = SelectObject(hMemoryDC, hBitmap);
  691.  
  692.     if (lpPoint = (LPPOINT) malloc(sizeof(POINT) * n)) {
  693.          hBrush = CreateSolidBrush(carray[cur_color]);
  694.         if (hBrush) {
  695.             r.left = r.right = x[0];
  696.             r.top = r.bottom = y[0];
  697.             for (i = 0; i < n; i++) {
  698.                 lpPoint[i].x = x[i];
  699.                 if (lpPoint[i].x < r.left) r.left = lpPoint[i].x;
  700.                 else if (lpPoint[i].x > r.right) r.right = lpPoint[i].x;
  701.  
  702.                 lpPoint[i].y = vdevice.sizeSy - y[i];
  703.                 if (lpPoint[i].y < r.top) r.top = lpPoint[i].y;
  704.                 else if (lpPoint[i].y > r.bottom) r.bottom = lpPoint[i].y;
  705.                 }
  706.             hOldBrush = SelectObject(hMemoryDC, hBrush);
  707.             OldPolyMode = GetPolyFillMode(hMemoryDC);
  708.             SetPolyFillMode(hMemoryDC, WINDING);
  709.             Polygon(hMemoryDC, lpPoint, n);
  710.             if (use_front_buf) {
  711.                 hDC = GetDC(hWinder);
  712.                 BitBlt(hDC,
  713.                     r.left, r.top,
  714.                     r.right - r.left + 1,
  715.                     r.bottom - r.top + 1,
  716.                     hMemoryDC,
  717.                     r.left, r.top,
  718.                     SRCCOPY);
  719.                 ReleaseDC(hWinder, hDC);
  720.                 }
  721.             else {
  722.                 /* invalidate the region in front buffer */
  723.                 mswin_invalidate_rect(&r);
  724.                 }
  725.  
  726.             SetPolyFillMode(hMemoryDC, OldPolyMode);
  727.             SelectObject(hMemoryDC, hOldBrush);
  728.             DeleteObject(hBrush);
  729.             }
  730.         free(lpPoint);
  731.         }
  732.     hOldBitmap = SelectObject(hMemoryDC, hOldBitmap);
  733.  
  734.     vdevice.cpVx = x[n-1];
  735.     vdevice.cpVy = y[n-1];
  736.  
  737.     mswin_msg_loop();
  738. }
  739.  
  740.  
  741.  
  742. int        mswin_color(i)
  743. int        i;
  744. {
  745.     cur_color = (unsigned)i;
  746. }
  747.  
  748.  
  749.  
  750. int        mswin_mapcolor(i, r, g, b)
  751. int        i, r, g, b;
  752. {
  753.     if (i >= CMAPSIZE) return(-1);
  754.  
  755.     carray[i] = RGB(r, g, b);
  756.  
  757.     mswin_msg_loop();
  758.     return 0;
  759. }
  760.  
  761.  
  762.  
  763. int        mswin_char(c)
  764. char    c;
  765. {
  766.     HDC    hDC;        
  767.     char    s[2];
  768.     HBITMAP    hOldBitmap;
  769.     RECT    r;
  770.     int    OldBkMode;
  771.     DWORD    OldTextColour;
  772.  
  773.     hOldBitmap = SelectObject(hMemoryDC, hBitmap);
  774.  
  775.     s[0] = c;
  776.     s[1] = '\0';
  777.  
  778.     OldBkMode = SetBkMode(hMemoryDC, TRANSPARENT);
  779.     OldTextColour = SetTextColor(hMemoryDC, carray[cur_color]);
  780.     TextOut(hMemoryDC, r.left = vdevice.cpVx, r.top = vdevice.sizeSy - vdevice.cpVy, s, 1);
  781.     SetTextColor(hMemoryDC, OldTextColour);
  782.     SetBkMode(hMemoryDC, OldBkMode);
  783.  
  784.     if (use_front_buf) {
  785.         hDC = GetDC(hWinder);
  786.         BitBlt(hDC,
  787.             r.left, r.top,
  788.             xChar,
  789.             yChar,
  790.             hMemoryDC,
  791.             r.left, r.top,
  792.             SRCCOPY);
  793.         ReleaseDC(hWinder, hDC);
  794.         }
  795.     else {
  796.         /* invalidate the region in front buffer */
  797.         r.right = r.left + xChar;
  798.         r.bottom = r.top + yChar;
  799.         mswin_invalidate_rect(&r);
  800.         }
  801.  
  802.     hOldBitmap = SelectObject(hMemoryDC, hOldBitmap);
  803.  
  804.     mswin_msg_loop();
  805. }
  806.  
  807.  
  808.  
  809. int        mswin_string(s)
  810. char    *s;
  811. {
  812.     HDC    hDC;
  813.     HBITMAP    hOldBitmap;
  814.     RECT    r;
  815.     int    n;
  816.     int    OldBkMode;
  817.     DWORD    OldTextColour;
  818.  
  819.     hOldBitmap = SelectObject(hMemoryDC, hBitmap);
  820.  
  821.     OldBkMode = SetBkMode(hMemoryDC, TRANSPARENT);
  822.     OldTextColour = SetTextColor(hMemoryDC, carray[cur_color]);
  823.     TextOut(hMemoryDC, r.left = vdevice.cpVx, r.top = vdevice.sizeSy - vdevice.cpVy, s, n = strlen(s));
  824.     SetTextColor(hMemoryDC, OldTextColour);
  825.     SetBkMode(hMemoryDC, OldBkMode);
  826.     if (use_front_buf) {
  827.         hDC = GetDC(hWinder);
  828.         BitBlt(hDC,
  829.             r.left, r.top,
  830.             n * xChar,
  831.             yChar,
  832.             hMemoryDC,
  833.             r.left, r.top,
  834.             SRCCOPY);
  835.         ReleaseDC(hWinder, hDC);
  836.         }
  837.     else {
  838.         /* invalidate the region in front buffer */
  839.         r.right = r.left + n * xChar;
  840.         r.bottom = r.top + yChar;
  841.         mswin_invalidate_rect(&r);
  842.         }
  843.  
  844.     hOldBitmap = SelectObject(hMemoryDC, hOldBitmap);
  845.  
  846.     mswin_msg_loop();
  847. }
  848.  
  849.  
  850.  
  851. int        mswin_font(font)
  852. char    *font;
  853. {
  854.     /* NOT IMPLEMENTED */
  855.     mswin_msg_loop();
  856.     return 1;
  857. }
  858.  
  859.  
  860.  
  861. int        mswin_frontbuf()
  862. {
  863.     use_front_buf = TRUE;
  864.     mswin_msg_loop();
  865. }
  866.  
  867.  
  868.  
  869. int        mswin_backbuf()
  870. {
  871.     use_front_buf = FALSE;
  872.     BackRect.left = BackRect.top = 32765;
  873.     BackRect.right = BackRect.bottom = -32765;
  874.     mswin_msg_loop();
  875.     return 1;
  876. }
  877.  
  878.  
  879.  
  880. int        mswin_swapbuf()
  881. {
  882.     HDC    hDC;
  883.     RECT    r;
  884.     HBITMAP    hOldBitmap;
  885.  
  886.     hDC = GetDC(hWinder);
  887.     hOldBitmap = SelectObject(hMemoryDC, hBitmap);
  888. #ifdef GUNGE
  889.     GetClientRect(hWinder, &r);
  890.     BitBlt(hDC,
  891.         r.left, r.top,
  892.         r.right - r.left,
  893.         r.bottom - r.top,
  894.         hMemoryDC,
  895.         r.left, r.top,
  896.         SRCCOPY);
  897. #endif
  898.     BitBlt(hDC,
  899.         BackRect.left, BackRect.top,
  900.         BackRect.right - BackRect.left,
  901.         BackRect.bottom - BackRect.top,
  902.         hMemoryDC,
  903.         BackRect.left, BackRect.top,
  904.         SRCCOPY);
  905.     BackRect.left = BackRect.top = 32765;
  906.     BackRect.right = BackRect.bottom = -32765;
  907.  
  908.     ReleaseDC(hWinder, hDC);
  909.     SelectObject(hMemoryDC, hOldBitmap);
  910.  
  911.     mswin_msg_loop();
  912. }
  913.  
  914.  
  915.  
  916. int        mswin_checkkey()
  917. {
  918.     MSG    Msg;
  919.  
  920.     while (PeekMessage(&Msg, NULL, NULL, NULL, PM_NOREMOVE)) {
  921.         GetMessage(&Msg, NULL, NULL, NULL);
  922.         TranslateMessage(&Msg);       /* Translates virtual key codes         */
  923.         DispatchMessage(&Msg);       /* Dispatches message to window         */
  924.         }
  925.     if (Msg.message == WM_QUIT) {
  926.         mswin_cleanup();
  927.         exit(Msg.wParam);
  928.         }
  929.  
  930.     return current_key;
  931. }
  932.  
  933.  
  934.  
  935. int        mswin_getkey()
  936. {
  937.     MSG    Msg;
  938.     WORD    quit;
  939.  
  940.     while (GetMessage(&Msg, NULL, NULL, NULL)) {
  941.         TranslateMessage(&Msg);       /* Translates virtual key codes         */
  942.         DispatchMessage(&Msg);       /* Dispatches message to window         */
  943.         if (Msg.message == WM_CHAR && vogle_active) break;
  944.         }
  945.     if (Msg.message == WM_QUIT) {
  946.         mswin_cleanup();
  947.         exit(Msg.wParam);
  948.         }
  949.     return (Msg.wParam);
  950. }
  951.  
  952.  
  953.  
  954. int        mswin_locator(x, y)
  955. int        *x, *y;
  956. {
  957.     mswin_msg_loop();
  958.  
  959.     *x = xMouse;
  960.     *y = vdevice.sizeSy - yMouse;
  961.     return (LButton | (MButton << 2) | (RButton << 1));
  962. }
  963.  
  964.  
  965.  
  966. int        mswin_verror(msg)
  967. char        *msg;
  968. {
  969.     PostMessage(hWinder, WM_VOGLE_ERROR, NULL, (DWORD)((LPSTR) msg));
  970.     mswin_msg_loop();
  971. }
  972.  
  973.  
  974. void
  975. mswin_setlw(w)
  976. {
  977.     if (w == 0)
  978.         lwidth = 1;
  979.     else
  980.         lwidth = 3;
  981. }
  982.  
  983. /*
  984.  * the device entry
  985.  */
  986. static DevEntry mswindev = {
  987.     "mswin",
  988.     "large",
  989.     "small",
  990.     mswin_backbuf,
  991.     mswin_char,
  992.     mswin_checkkey,
  993.     mswin_clear,
  994.     mswin_color,
  995.     mswin_draw,
  996.     mswin_exit,
  997.     mswin_fill,
  998.     mswin_font,
  999.     mswin_frontbuf,
  1000.     mswin_getkey,
  1001.     mswin_init,
  1002.     mswin_locator,
  1003.     mswin_mapcolor,
  1004.     mswin_setlw,
  1005.     mswin_string,
  1006.     mswin_swapbuf,
  1007.     noop
  1008. };
  1009.  
  1010. /*
  1011.  * _mswin_devcpy
  1012.  *
  1013.  *    copy the mswin device into vdevice.dev.
  1014.  */
  1015. int        _mswin_devcpy()
  1016. {
  1017.     vdevice.dev = mswindev;
  1018. }
  1019.  
  1020.  
  1021.  
  1022. static
  1023. void    swap(a, b)
  1024. int        *a;
  1025. int        *b;
  1026. {
  1027.     int    t;
  1028.  
  1029.     t = *a;
  1030.     *a = *b;
  1031.     *b = t;
  1032. }
  1033.  
  1034.