_os2.c
Upload User: gzelex
Upload Date: 2007-01-07
Package Size: 707k
Code Size: 27k
Development Platform:

MultiPlatform

  1. /*******************************************************************************
  2. +
  3. +  LEDA-R  3.2.2
  4. +
  5. +  _os2.c
  6. +
  7. +  Copyright (c) 1995  by  Max-Planck-Institut fuer Informatik
  8. +  Im Stadtwald, 66123 Saarbruecken, Germany     
  9. +  All rights reserved.
  10. *******************************************************************************/
  11. //-----------------------------------------------------------------------------
  12. // basic graphics routines for OS/2  (PM)
  13. //
  14. // s.n. (May & April 1995)
  15. //-----------------------------------------------------------------------------
  16. #include <LEDA/impl/x_basic.h>
  17. #include <string.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <math.h>
  21. #define INCL_WIN
  22. #define INCL_GPI
  23. #include <os2.h>
  24. #define LEDA_ID         1
  25. #define TEXT_FONT_ID    1
  26. #define BOLD_FONT_ID    2
  27. #define IDM_FILE        1
  28. #define IDM_EXIT        2
  29. #define IDM_FONT        3
  30. typedef void (*redraw_fct)();
  31. struct OS2_Window {
  32. HWND hwndFrame;
  33. HWND hwnd;
  34. HPS  hps_mem;
  35. HPS  hps_scr;
  36. int  bg_col;
  37. int  xmax;
  38. int  ymax;
  39. int  refresh;
  40. int  iconized;
  41. redraw_fct redraw;
  42. };
  43. #define YCOORD(w,ypix)  (wlist[w].ymax - ypix)
  44. // global data
  45. static HAB hab;
  46. static HMQ hmq;
  47. static FATTRS TextFattrs;
  48. static FATTRS BoldFattrs;
  49. static FATTRS MesgFattrs;
  50. static FONTMETRICS FontMetrics;
  51. struct event {
  52. int win;
  53. int kind;
  54. int val;
  55. int x;
  56. int y;
  57. unsigned long t;
  58. };
  59. static event cur_event;
  60. #define  MAX_WIN 32
  61. static OS2_Window wlist[MAX_WIN+1];
  62. static Window wcount = 0;
  63. static LONG   rgb_table[32];
  64. static ULONG* color_table;
  65. static ULONG  color_table_src[16];
  66. static ULONG  color_table_xor[16];
  67. static long mode_table[4];
  68. static long lstyle_table[4];
  69. static int GCOLOR;
  70. static int MODE;
  71. static int LSTYLE;
  72. static int LWIDTH;
  73. static int shift_key_down = 0;
  74. static int ctrl_key_down = 0;
  75. static int alt_key_down = 0;
  76. /* display */
  77. static void message(char* s)
  78. { WinAlarm( HWND_DESKTOP, WA_ERROR );
  79.   WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, (PSZ) s, 
  80.                  (PSZ)"LEDA WINDOW MESSAGE", 256, MB_OK);
  81. static void message(char* s, int i)
  82. { WinAlarm( HWND_DESKTOP, WA_ERROR );
  83.   char msg[256];
  84.   sprintf(msg,s,i);
  85.   WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, (PSZ) msg, 
  86.                 (PSZ)"LEDA WINDOW MESSAGE", 256, MB_OK);
  87. static void message(char* s, int i, int j)
  88. { WinAlarm( HWND_DESKTOP, WA_ERROR );
  89.   char msg[256];
  90.   sprintf(msg,s,i,j);
  91.   WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, (PSZ) msg, 
  92.                 (PSZ)"LEDA WINDOW MESSAGE", 256, MB_OK);
  93. static void init_palette(HWND hwnd,HPS hps)
  94. {
  95. #define LONGFromRGB(R,G,B) (LONG)(((LONG)R<<16)+((LONG)G<<8)+(LONG)B)
  96.              // wi bl  re  gr  bl  ye  vi  or  cy  br  pi  gr  bl  g1  g2  g3
  97. unsigned char 
  98.       R[16] = {255, 0,255, 32,  0,255,160,255,  0,192,255,  0,  0,212,180,116};
  99. unsigned char 
  100.       G[16] = {255, 0,  0,255,  0,255,  0,160,192,112,  0,160,128,212,180,116};
  101. unsigned char 
  102.       B[16] = {255, 0,  0,  0,213,  0,208,  0,192, 56,255,100,255,212,180,116};
  103.   for (int i=0; i < 16; i++) 
  104.   { rgb_table[2*i] = i;
  105.     rgb_table[2*i+1] = LONGFromRGB(R[i],G[i],B[i]);
  106.    }
  107.   if (!GpiCreateLogColorTable(hps,LCOL_PURECOLOR,LCOLF_INDRGB,0,32,rgb_table))
  108.      message("cannot create color table");
  109. /*
  110.    ULONG   cclr;
  111.    int i;
  112.    for (i=0; i < 16; i++) 
  113.       rgb_table[i] = LONGFromRGB(R[i],G[i],B[i]);
  114.    HPAL hPal = GpiCreatePalette( hab,
  115.              (ULONG) LCOL_PURECOLOR,
  116.          (ULONG) LCOLF_CONSECRGB,
  117.          32,
  118.          rgb_table );
  119.    if( hPal == NULLHANDLE || hPal == GPI_ERROR)
  120.       message("GpiCreatePalette Error");
  121.    else 
  122.       if (GpiSelectPalette(hps, hPal ) == PAL_ERROR)
  123.         message("GpiSelectPalette Error");
  124.       else 
  125.         if (WinRealizePalette(hwnd,hps,&cclr) == PAL_ERROR)
  126.           message("WinRealizePalette Error");
  127. */
  128. }
  129. void open_display(void)
  130. { hab = WinInitialize (0);
  131.   hmq = WinCreateMsgQueue (hab, 0);
  132.   int i;
  133.   for(i=0; i < 16; i++) color_table_src[i] = color_table_xor[i] = i;
  134.   color_table_xor[white] = black;
  135.   color_table_xor[black] = white;
  136.   color_table_xor[red]   = cyan;
  137.   color_table_xor[green] = violet;
  138.   color_table_xor[blue]  = yellow;
  139.   color_table_xor[yellow]= blue;
  140.   color_table_xor[violet]= green;
  141.   color_table_xor[orange]= blue2;
  142.   color_table_xor[blue2] = orange;
  143.   color_table_xor[pink]  = green;
  144.   color_table = color_table_src;
  145.   GCOLOR = black;
  146.   mode_table[src_mode] = FM_OVERPAINT;
  147.   mode_table[or_mode]  = FM_OR;
  148.   mode_table[xor_mode] = FM_XOR;
  149.   mode_table[and_mode] = FM_AND;
  150.   MODE = src_mode;
  151.   lstyle_table[dotted] = LINETYPE_DOT;
  152.   lstyle_table[dashed] = LINETYPE_LONGDASH;
  153.   lstyle_table[solid]  = LINETYPE_SOLID;
  154.   LSTYLE = solid;
  155.   LWIDTH = 1;
  156.   HPS hps = WinGetPS(HWND_DESKTOP);
  157.   TextFattrs.usRecordLength  = sizeof(FATTRS);
  158.   TextFattrs.fsSelection     = 0;
  159.   TextFattrs.lMatch          = 0L;
  160.   TextFattrs.idRegistry      = 0;
  161.   TextFattrs.lMaxBaselineExt = 14L;
  162.   TextFattrs.lAveCharWidth   = 6L;
  163.   TextFattrs.fsType          = 0;
  164.   strcpy(TextFattrs.szFacename,"System VIO");
  165.   GpiCreateLogFont(hps,(PSTR8)NULL,TEXT_FONT_ID,&TextFattrs);
  166.   GpiSetCharSet(hps,TEXT_FONT_ID);
  167.   GpiQueryFontMetrics(hps,sizeof(FONTMETRICS),(PFONTMETRICS)&FontMetrics);
  168.   BoldFattrs.usRecordLength  = sizeof(FATTRS);
  169.   BoldFattrs.fsSelection     = 0;
  170.   BoldFattrs.lMatch          = 0L;
  171.   BoldFattrs.idRegistry      = 0;
  172.   BoldFattrs.lMaxBaselineExt = 14L;
  173.   BoldFattrs.lAveCharWidth   = 8L;
  174.   BoldFattrs.fsType          = 0;
  175.   strcpy(BoldFattrs.szFacename,"System VIO");
  176.   WinReleasePS(hps);
  177. }
  178. void close_display(void)
  179. { WinDestroyMsgQueue (hmq);
  180.   WinTerminate (hab);
  181.  }
  182. void flush_display(void)
  183. { //QMSG qmsg;
  184.   //if (WinPeekMsg(hab,&qmsg,0L,0,0,PM_REMOVE)) WinDispatchMsg (hab, &qmsg);
  185.  }
  186. static void refresh_win(Window w, int x0=0, int y0=0, int x1=0, int y1=0)
  187.   if (wlist[w].refresh) 
  188.   { if (x0 == 0 && x1 == 0) x1 = wlist[w].xmax;
  189.     if (y0 == 0 && y1 == 0) y1 = wlist[w].ymax;
  190.     if (x0 > x1) { int tmp = x0; x0 = x1; x1 = tmp; }
  191.     if (y0 > y1) { int tmp = y0; y0 = y1; y1 = tmp; }
  192.     int d = LWIDTH;
  193.     POINTL aptl[4];
  194.     aptl[0].x = x0-d;
  195.     aptl[0].y = y0-d;
  196.     aptl[1].x = x1+d;
  197.     aptl[1].y = y1+d;
  198.     aptl[2].x = x0-d;
  199.     aptl[2].y = y0-d;
  200.     aptl[3].x = x1+d;
  201.     aptl[3].y = y1+d;
  202.     GpiBitBlt(wlist[w].hps_scr,wlist[w].hps_mem,4,aptl,ROP_SRCCOPY,BBO_IGNORE);
  203.   }
  204. }
  205. void start_batch(Window w) {  wlist[w].refresh = 0; }
  206. void end_batch(Window w) 
  207. {  wlist[w].refresh = 1; 
  208.    refresh_win(w);
  209. }
  210.    
  211. int  display_width(void)
  212. { return WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN); }
  213. int  display_height(void)
  214. { return WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN); }
  215. /*
  216. int  mouse_buttons(void)
  217. { return WinQuerySysValue(HWND_DESKTOP, SV_CMOUSEBUTTONS); }
  218. */
  219. int  display_depth(void) { return 16; }
  220. /* windows */
  221. static void font_dialog(HWND hwnd)
  222.   FONTDLG FontDlg;
  223.   char szFamilyname[FACESIZE];
  224.   szFamilyname[0] = 0;
  225.   memset((PCH)&FontDlg,0,sizeof(FONTDLG));
  226.   FontDlg.cbSize         = sizeof(FONTDLG);
  227.   FontDlg.hpsScreen      = WinGetPS(hwnd);
  228.   FontDlg.pszFamilyname  = (PSZ)szFamilyname;
  229.   FontDlg.usFamilyBufLen = FACESIZE;
  230.   FontDlg.pszPreview     = (PSZ)"Sample Text";
  231.   FontDlg.fl             = FNTS_RESETBUTTON | FNTS_CENTER |
  232.                            FNTS_INITFROMFATTRS | FNTS_BITMAPONLY;
  233.   FontDlg.flStyle        = FATTR_SEL_ITALIC;
  234.   FontDlg.clrFore        = CLR_BLACK;
  235.   FontDlg.clrBack        = CLR_PALEGRAY;
  236.   FontDlg.fAttrs         = TextFattrs;
  237.   FontDlg.pszTitle       = (PSZ)"FONT SELECTION";
  238.   
  239.   WinFontDlg(HWND_DESKTOP,hwnd,(PFONTDLG)&FontDlg);
  240.   if (FontDlg.lReturn == DID_OK)
  241.   {  char msg[256];
  242.      TextFattrs = FontDlg.fAttrs;
  243.      sprintf(msg,"Facename = %s  MaxBaseLinExt = %d CharWidth = %d", 
  244.              TextFattrs.szFacename,
  245.              TextFattrs.lMaxBaselineExt,
  246.              TextFattrs.lAveCharWidth);
  247.      message(msg);
  248.      GpiCreateLogFont(FontDlg.hpsScreen,(PSTR8)NULL,TEXT_FONT_ID,&TextFattrs);
  249.      GpiSetCharSet(FontDlg.hpsScreen,TEXT_FONT_ID);
  250.      GpiQueryFontMetrics(FontDlg.hpsScreen,sizeof(FONTMETRICS),(PFONTMETRICS)&FontMetrics);
  251.    }
  252.   WinReleasePS(FontDlg.hpsScreen);
  253. }
  254. static MRESULT EXPENTRY ClientWndProc (HWND hwnd, ULONG msg,
  255.                                        MPARAM mp1, MPARAM mp2)
  256. {
  257.   for(int w = 1; w<=wcount; w++)
  258.      if (wlist[w].hwnd == hwnd) break;
  259.   cur_event.win = w;
  260.   switch (msg) {
  261.   case WM_SIZE: 
  262.         { RECTL rcl;
  263.           WinQueryWindowRect(hwnd, &rcl);
  264.           wlist[w].xmax = rcl.xRight;
  265.           wlist[w].ymax = rcl.yTop;
  266.           if (rcl.xRight != 0  && !wlist[w].iconized) 
  267.           { cur_event.kind = configure_event;
  268.             cur_event.x = rcl.xRight;
  269.             cur_event.y = rcl.yTop;
  270.             if (wlist[w].redraw) clear_window(w);
  271.            }
  272.            wlist[w].iconized = (rcl.xRight == 0);
  273. /*
  274.           // have to adjust bitmap (how is it done ?)
  275.           HPS hps = wlist[w].hps_scr;
  276.           BITMAPINFOHEADER2 bmp = {16, 0, 0, 4, 1}; 
  277.           bmp.cx = cur_event.x;
  278.           bmp.cy = cur_event.y;
  279.           HBITMAP hbm = GpiCreateBitmap(hps, &bmp, 0L, NULL, NULL);
  280.           if (hbm == 0) message("cannot create bitmap");
  281.           HBITMAP hbm_prev = GpiSetBitmap(hps, hbm);
  282.           GpiDeleteBitmap(hbm_prev);
  283. */
  284.           break;
  285.          }
  286.   case WM_PAINT: 
  287.         { HPS hps = WinBeginPaint(hwnd,wlist[w].hps_scr,0); 
  288.           refresh_win(w);
  289.           WinEndPaint(hps);
  290.           return ((MRESULT)0);
  291.          }
  292.   case WM_QUIT: 
  293.   case WM_CLOSE: 
  294.          cur_event.kind = destroy_event;
  295.          close_display();
  296.          exit(0);
  297.   case WM_BUTTON1DBLCLK: 
  298.   case WM_BUTTON1DOWN: 
  299.          cur_event.kind = button_press_event;
  300.          cur_event.val = 1;
  301.          cur_event.x = SHORT1FROMMP(mp1);
  302.          cur_event.y = YCOORD(w,SHORT2FROMMP(mp1));
  303.          if (shift_key_down) cur_event.val = -cur_event.val;
  304.          if (ctrl_key_down)  cur_event.val += 3;
  305.          break;
  306.   case WM_BUTTON2DBLCLK: 
  307.   case WM_BUTTON2DOWN: 
  308.          cur_event.kind = button_press_event;
  309.          cur_event.val = 3;
  310.          cur_event.x = SHORT1FROMMP(mp1);
  311.          cur_event.y = YCOORD(w,SHORT2FROMMP(mp1));
  312.          if (shift_key_down) cur_event.val = -cur_event.val;
  313.          if (ctrl_key_down)  cur_event.val += 3;
  314.          break;
  315. /*
  316.   case WM_BUTTON3DOWN: 
  317. */
  318.   case WM_BUTTON1UP: 
  319.          cur_event.kind = button_release_event;
  320.          cur_event.val = 1;
  321.          cur_event.x = SHORT1FROMMP(mp1);
  322.          cur_event.y = YCOORD(w,SHORT2FROMMP(mp1));
  323.          if (shift_key_down) cur_event.val = -cur_event.val;
  324.          if (ctrl_key_down)  cur_event.val += 3;
  325.          break;
  326.   case WM_BUTTON2UP: 
  327.          cur_event.kind = button_release_event;
  328.          cur_event.val = 3;
  329.          cur_event.x = SHORT1FROMMP(mp1);
  330.          cur_event.y = YCOORD(w,SHORT2FROMMP(mp1));
  331.          if (shift_key_down) cur_event.val = -cur_event.val;
  332.          if (ctrl_key_down)  cur_event.val += 3;
  333.          break;
  334. /*
  335.   case WM_BUTTON3UP: 
  336. */
  337.   case WM_MOUSEMOVE: 
  338.          cur_event.kind = motion_event;
  339.          cur_event.x = SHORT1FROMMP(mp1);
  340.          cur_event.y = YCOORD(w,SHORT2FROMMP(mp1));
  341.          break;
  342.   case WM_CHAR: 
  343.         { USHORT fsKeyFlags = (USHORT) SHORT1FROMMP(mp1);
  344.           if (fsKeyFlags & KC_KEYUP) 
  345.              { //key up
  346.                shift_key_down = 0;
  347.                ctrl_key_down = 0;
  348.                alt_key_down = 0;
  349.               }
  350.           else // key down
  351.              { if (fsKeyFlags & KC_SHIFT) shift_key_down = 1;
  352.                if (fsKeyFlags & KC_CTRL)  ctrl_key_down = 1;
  353.                if (fsKeyFlags & KC_ALT)   alt_key_down = 1;
  354.                if (fsKeyFlags & KC_CHAR )
  355.                { cur_event.val = SHORT1FROMMP(mp2);
  356.                  cur_event.kind = key_press_event;
  357.                 }
  358.               }
  359.            break;
  360.          }
  361.     case WM_ERASEBACKGROUND:
  362.           return (MRFROMLONG(1L));
  363.      
  364.     case WM_COMMAND:
  365.       switch (SHORT1FROMMP (mp1))
  366.       { 
  367.         case IDM_FONT:
  368.            font_dialog(hwnd);
  369.            return ((MRESULT)0);
  370.         case IDM_EXIT:
  371.            WinSendMsg (hwnd, WM_CLOSE, NULL, NULL);
  372.            return ((MRESULT)0);
  373.         }
  374.     }
  375.    return WinDefWindowProc (hwnd, msg, mp1, mp2);
  376. }
  377. Window open_window(int x,int y,int width,int height,int bg_col, 
  378.                    const char* header, const char* label)
  379. {
  380.   ULONG flFrameFlags;
  381.   HWND hwndFrame;
  382.   HWND hwnd;
  383.   if (wcount == MAX_WIN) 
  384.       message("Maximal number of windows (%d) exceeded",MAX_WIN);
  385.   WinRegisterClass (hab,(PSZ)"LEDA-WINDOW", ClientWndProc, CS_SAVEBITS, 0L);
  386.   //WinRegisterClass (hab,(PSZ)"LEDA-WINDOW", ClientWndProc, 0, 0L);
  387.   flFrameFlags = (FCF_TITLEBAR      | 
  388.                   FCF_SYSMENU       |
  389.                   FCF_SIZEBORDER    | 
  390.                   FCF_MINMAX        |
  391.                   FCF_ACCELTABLE    |
  392. //                FCF_MENU          | 
  393. //                FCF_SHELLPOSITION | 
  394.                   FCF_ICON          | 
  395.                   FCF_TASKLIST);
  396.   FRAMECDATA FrameData;
  397.   FrameData.cb = sizeof(FRAMECDATA);
  398.   FrameData.flCreateFlags = flFrameFlags;
  399.   FrameData.hmodResources = 0;
  400.   FrameData.idResources = LEDA_ID;
  401.   hwndFrame = WinCreateWindow (HWND_DESKTOP, WC_FRAME, (PSZ)header,
  402.                                0L, 0, 0, 0, 0, 0, HWND_TOP, LEDA_ID,
  403.                                (PVOID)(PFRAMECDATA)&FrameData, NULL);
  404.   hwnd = WinCreateWindow(hwndFrame,(PSZ)"LEDA-WINDOW", NULL, 
  405.                                0L, 0, 0, 0, 0, hwndFrame, HWND_TOP, FID_CLIENT,
  406.                                NULL, NULL);
  407.   WinShowWindow(hwndFrame,TRUE);
  408.   //height += WinQuerySysValue(HWND_DESKTOP, SV_CYMENU); 
  409.   height += WinQuerySysValue(HWND_DESKTOP, SV_CYTITLEBAR); 
  410.   height += WinQuerySysValue(HWND_DESKTOP, SV_CYSIZEBORDER);
  411.   width  += 2*WinQuerySysValue(HWND_DESKTOP, SV_CXSIZEBORDER);
  412.   y = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - height - y; 
  413.   WinSetWindowPos(hwndFrame, 0L, x, y, width, height, SWP_MOVE | SWP_SIZE );
  414.   // create screen presentation space
  415.   SIZEL sizel = {0,0};
  416.   HDC hdc = WinOpenWindowDC(hwnd);
  417.   HPS hps_scr = GpiCreatePS(hab,hdc,&sizel,PU_PELS | GPIF_DEFAULT | 
  418.                                               GPIT_NORMAL | GPIA_ASSOC);
  419.   if (hps_scr == 0) message("cannot create client hps");
  420.  
  421.  // create memory device context and presentation space, 
  422.   DEVOPENSTRUC dop = {NULL,(PSZ)"DISPLAY",NULL,NULL,NULL,NULL,NULL,NULL,NULL};
  423.   HDC hdc_mem = DevOpenDC(hab, OD_MEMORY, (PSZ)"*", 5L,(PDEVOPENDATA)&dop, 
  424.                                                                 NULLHANDLE);
  425.   HPS hps_mem = GpiCreatePS(hab,hdc_mem,&sizel, GPIA_ASSOC | GPIT_NORMAL | PU_PELS);
  426.   if (hps_mem == 0) message("cannot create memory hps");
  427.   BITMAPINFOHEADER2 bmp = {16, 0, 0, 4, 1}; 
  428.   bmp.cx =  width;
  429.   bmp.cy =  height;
  430.   HBITMAP hbm = GpiCreateBitmap(hps_mem, &bmp, 0L, NULL, NULL);
  431.   if (hbm == 0) message("cannot create bitmap");
  432.   GpiSetBitmap(hps_mem, hbm);
  433.  
  434.   // create and set font
  435.   if (GpiCreateLogFont(hps_mem,(PSTR8)NULL,TEXT_FONT_ID,&TextFattrs) == FALSE)
  436.      message("cannot create font");
  437.   GpiSetCharSet(hps_mem,TEXT_FONT_ID);
  438.   GpiQueryFontMetrics(hps_mem,sizeof(FONTMETRICS),(PFONTMETRICS)&FontMetrics);
  439.   QMSG qmsg;
  440.   while (WinPeekMsg(hab,&qmsg,0L,0,0,PM_REMOVE)) WinDispatchMsg (hab, &qmsg);
  441.   // initialize color table
  442.   init_palette(hwnd,hps_mem);
  443.   // set default values for drawing parameters
  444.   GpiSetMix(hps_mem,mode_table[MODE]);
  445.   GpiSetColor(hps_mem,color_table[GCOLOR]);
  446.   GpiSetBackColor(hps_mem,color_table[bg_col]);
  447.   GpiSetLineType(hps_mem,lstyle_table[LSTYLE]);
  448.   // get window dimensions
  449.   SWP swp;
  450.   WinQueryWindowPos(hwnd, &swp);
  451.   wcount++;
  452.   wlist[wcount].hwndFrame = hwndFrame;
  453.   wlist[wcount].hwnd = hwnd;
  454.   wlist[wcount].hps_mem = hps_mem;
  455.   wlist[wcount].hps_scr = hps_scr;
  456.   wlist[wcount].bg_col = bg_col;
  457.   wlist[wcount].refresh = 1;
  458.   wlist[wcount].iconized = 0;
  459.   wlist[wcount].redraw = 0;
  460.   wlist[wcount].xmax = swp.cx-1;
  461.   wlist[wcount].ymax = swp.cy-1;
  462.   WinSetActiveWindow(HWND_DESKTOP,hwndFrame);
  463.   clear_window(wcount);
  464.   return wcount;
  465. }
  466. void close_window(Window win) 
  467. { GpiAssociate(wlist[win].hps_mem, NULLHANDLE); 
  468.   GpiDestroyPS(wlist[win].hps_mem); 
  469.   GpiAssociate(wlist[win].hps_scr, NULLHANDLE); 
  470.   GpiDestroyPS(wlist[win].hps_scr); 
  471.   WinDestroyWindow(wlist[win].hwndFrame); 
  472.  }
  473. void set_header(Window win, const char *s)
  474. { WinSetWindowText(wlist[win].hwndFrame, (PSZ)s);
  475.   WinInvalidateRect(WinWindowFromID(wlist[win].hwndFrame, FID_TITLEBAR),
  476.                                                      (PRECTL)NULL, FALSE);
  477.  }
  478. void set_redraw(Window w, void (*f)()) 
  479. { wlist[w].redraw = f; }
  480. int window_width(Window win)
  481. { SWP swp;
  482.   WinQueryWindowPos(wlist[win].hwnd, &swp);
  483.   return swp.cx;
  484.  }
  485. int window_height(Window win)
  486. { SWP swp;
  487.   WinQueryWindowPos(wlist[win].hwnd, &swp);
  488.   return swp.cy;
  489.  }
  490. void window_position(Window win, int* x, int* y)
  491. { SWP swp;
  492.   WinQueryWindowPos(wlist[win].hwnd, &swp);
  493.   *x = swp.x;
  494.   *y = swp.y;
  495.  }
  496. void clear_window(Window win)
  497. { // dispatch all pending messages first
  498.   QMSG qmsg;
  499.   while (WinPeekMsg(hab,&qmsg,0L,0,0,PM_REMOVE)) WinDispatchMsg (hab, &qmsg);
  500.   RECTL rcl;
  501.   WinQueryWindowRect(wlist[win].hwnd, &rcl);
  502.   int save_mode = set_mode(src_mode);
  503.   WinFillRect(wlist[win].hps_mem,&rcl,color_table[wlist[win].bg_col]);
  504.   set_mode(save_mode);
  505.   refresh_win(win);
  506. }
  507. /* drawing */
  508. void line(Window win, int x1, int y1, int x2, int y2)
  509. { POINTL pos;
  510.   HPS hps = wlist[win].hps_mem;
  511.   y1 = YCOORD(win,y1);
  512.   y2 = YCOORD(win,y2);
  513.   GpiBeginPath(hps,1L);
  514.   pos.x = x1;
  515.   pos.y = y1;
  516.   GpiMove(hps,&pos);
  517.   pos.x = x2;
  518.   pos.y = y2;
  519.   GpiLine(hps,&pos);
  520.   GpiEndPath(hps);
  521.   GpiStrokePath(hps,1L,0L);
  522.   refresh_win(win,x1,y1,x2,y2);
  523.  }
  524. void rectangle(Window win, int x1, int y1, int x2, int y2)
  525. { POINTL pos;
  526.   HPS hps = wlist[win].hps_mem;
  527.   y1 = YCOORD(win,y1);
  528.   y2 = YCOORD(win,y2);
  529.   pos.x = x1;
  530.   pos.y = y1;
  531.   GpiMove(hps,&pos);
  532.   pos.x = x2;
  533.   pos.y = y2;
  534.   GpiBox(hps,DRO_OUTLINE,&pos,0,0);
  535.   refresh_win(win,x1,y1,x2,y2);
  536.  }
  537. void box(Window win, int x1, int y1, int x2, int y2)
  538. { POINTL pos;
  539.   HPS hps = wlist[win].hps_mem;
  540.   y1 = YCOORD(win,y1);
  541.   y2 = YCOORD(win,y2);
  542.   pos.x = x1;
  543.   pos.y = y1;
  544.   GpiMove(hps,&pos);
  545.   pos.x = x2;
  546.   pos.y = y2;
  547.   GpiBox(hps,DRO_OUTLINEFILL,&pos,0,0);
  548.   refresh_win(win,x1,y1,x2,y2);
  549.  }
  550. void circle(Window win, int x, int y, int r)
  551. { HPS hps = wlist[win].hps_mem;
  552.   ARCPARAMS  arcparams; 
  553.   POINTL     center;
  554.   y = YCOORD(win,y);
  555.   arcparams.lP = r;
  556.   arcparams.lQ = r;
  557.   arcparams.lR = 0;
  558.   arcparams.lS = 0;
  559.   GpiSetArcParams(hps, (PARCPARAMS)&arcparams);
  560.   center.x = x;
  561.   center.y = y;
  562.   GpiBeginPath(hps,1L);
  563.   GpiMove (hps,&center);
  564.   GpiFullArc(hps,DRO_OUTLINE,MAKEFIXED(1,0));
  565.   GpiEndPath(hps);
  566.   GpiStrokePath(hps,1L,0L);
  567.   int d= int(0.7 * r + 1);
  568.   refresh_win(win,x-r,y-d,x-d,y+d);
  569.   refresh_win(win,x+d,y-d,x+r,y+d);
  570.   refresh_win(win,x-d,y-r,x+d,y-d);
  571.   refresh_win(win,x-d,y+d,x+d,y+r);
  572. }
  573. void fill_circle(Window win, int x, int y, int r)
  574. { HPS hps = wlist[win].hps_mem;
  575.   ARCPARAMS  arcparams; 
  576.   POINTL     center;
  577.   y = YCOORD(win,y);
  578.   arcparams.lP = r;
  579.   arcparams.lQ = r;
  580.   arcparams.lR = 0;
  581.   arcparams.lS = 0;
  582.   GpiSetArcParams(hps, (PARCPARAMS)&arcparams);
  583.   center.x = x;
  584.   center.y = y;
  585.   GpiMove (hps,&center);
  586.   GpiFullArc(hps,DRO_OUTLINEFILL,MAKEFIXED(1,0));
  587.   refresh_win(win,x-r,y-r,x+r,y+r);
  588. }
  589. void pixel(Window win, int x, int y)
  590. { line(win,x,y,x,y); }
  591. void pixels(Window win, int n, int* x, int* y)
  592. { int save = wlist[win].refresh;
  593.   wlist[win].refresh = 0;
  594.   while (n--) pixel(win,x[n],y[n]);
  595.   wlist[win].refresh = 1;
  596.   refresh_win(win);
  597. }
  598. void point(Window win, int x, int y)
  599. { HPS hps = wlist[win].hps_mem;
  600.   y = YCOORD(win,y);
  601.   POINTL pos;
  602.   pos.x = x-2;
  603.   pos.y = y-2;
  604.   GpiMove(hps,&pos);
  605.   pos.x = x+2;
  606.   pos.y = y+2;
  607.   GpiLine(hps,&pos);
  608.   pos.x = x-2;
  609.   pos.y = y+2;
  610.   GpiMove(hps,&pos);
  611.   pos.x = x-1;
  612.   pos.y = y+1;
  613.   GpiLine(hps,&pos);
  614.   pos.x = x+1;
  615.   pos.y = y-1;
  616.   GpiMove(hps,&pos);
  617.   pos.x = x+2;
  618.   pos.y = y-2;
  619.   GpiLine(hps,&pos);
  620.   refresh_win(win,x-2,y-2,x+2,y+2);
  621.  }
  622. void arc(Window win,int mx,int my,int r1,int r2,double start,double angle)
  623. { HPS hps = wlist[win].hps_mem;
  624.   POINTL p[3];
  625.   p[0].x = mx + int(r1*cos(start));
  626.   p[0].y = YCOORD(win,my + int(r1*sin(start)));
  627.   p[1].x = mx + int(r1*cos(start+angle/2));
  628.   p[1].y = YCOORD(win,my + int(r1*sin(start+angle/2)));
  629.   p[2].x = mx + int(r1*cos(start+angle));
  630.   p[2].y = YCOORD(win,my + int(r1*sin(start+angle)));
  631.   GpiBeginPath(hps,1L);
  632.   GpiMove(hps,p);
  633.   GpiPointArc(hps,p+1);
  634.   GpiEndPath(hps);
  635.   GpiStrokePath(hps,1L,0L);
  636.   refresh_win(win,mx-r1,YCOORD(win,my-r2),mx+r1,YCOORD(win,my+r2));
  637. }
  638. void fill_arc(Window win,int x0,int y0,int r1,int r2,double start,double angle)
  639. {}
  640. void ellipse(Window win, int x, int y, int r1, int r2)
  641. { HPS hps = wlist[win].hps_mem;
  642.   ARCPARAMS  arcparams; 
  643.   POINTL     center;
  644.   y = YCOORD(win,y);
  645.   arcparams.lP = r1;
  646.   arcparams.lQ = r2;
  647.   arcparams.lR = 0;
  648.   arcparams.lS = 0;
  649.   GpiSetArcParams(hps, (PARCPARAMS)&arcparams);
  650.   center.x = x;
  651.   center.y = y;
  652.   GpiMove (hps,&center);
  653.   GpiFullArc(hps,DRO_OUTLINE,MAKEFIXED(1,0));
  654.   refresh_win(win,x-r1,y-r2,x+r1,y+r2);
  655. }
  656. void fill_ellipse(Window win, int x, int y, int r1, int r2)
  657. { HPS hps = wlist[win].hps_mem;
  658.   ARCPARAMS  arcparams; 
  659.   POINTL     center;
  660.   y = YCOORD(win,y);
  661.   arcparams.lP = r1;
  662.   arcparams.lQ = r2;
  663.   arcparams.lR = 0;
  664.   arcparams.lS = 0;
  665.   GpiSetArcParams(hps, (PARCPARAMS)&arcparams);
  666.   center.x = x;
  667.   center.y = y;
  668.   GpiMove (hps,&center);
  669.   GpiFullArc(hps,DRO_OUTLINEFILL,MAKEFIXED(1,0));
  670.   refresh_win(win,x-r1,y-r2,x+r1,y+r2);
  671. }
  672. void fill_polygon(Window win, int n, int* xcoord, int* ycoord)
  673. { HPS hps = wlist[win].hps_mem;
  674.   POINTL*  p = new POINTL[n];
  675.   for(int i=0; i < n; i++) 
  676.   { p[i].x = xcoord[i];
  677.     p[i].y = YCOORD(win,ycoord[i]);
  678.    }
  679.   GpiMove(hps,p);
  680.   GpiBeginArea(hps,BA_BOUNDARY | BA_ALTERNATE);
  681.   GpiPolyLine(hps,n,p);
  682.   GpiEndArea(hps);
  683.   int xmin = 10000;
  684.   int ymin = 10000;
  685.   int xmax = 0;
  686.   int ymax = 0;
  687.   for(i=0; i < n; i++) 
  688.   { if (xmin > p[i].x) xmin = p[i].x;
  689.     if (xmax < p[i].x) xmax = p[i].x;
  690.     if (ymin > p[i].y) ymin = p[i].y;
  691.     if (ymax < p[i].y) ymax = p[i].y;
  692.    }
  693.   refresh_win(win,xmin,ymin,xmax,ymax);
  694.  }
  695. void put_text(Window win, int x, int y, const char* s, int l, int opaque)
  696. { int h = text_height(s);
  697.   int w = text_width(s);
  698.   if (opaque)
  699.   { int save_col = set_color(white);
  700.     int save_mode = set_mode(src_mode);
  701.     box(win,x,y,x+w,y+h);
  702.     set_color(save_col);
  703.     set_mode(save_mode);
  704.    }
  705.   y = YCOORD(win,y);
  706.   POINTL pos;
  707.   pos.x = x;
  708.   pos.y = y - FontMetrics.lMaxAscender;
  709.   int len = strlen(s);
  710.   if (len > 512) len = 512;
  711.   if (len > l) len = l;
  712.   GpiCharStringAt(wlist[win].hps_mem,&pos,len, (PSZ)s);
  713.   refresh_win(win,x,y,x+w,y-h);
  714.  }
  715.   
  716. void put_text(Window win, int x, int y, const char* s, int opaque)
  717. { put_text(win, x, y, s, 512, opaque); }
  718. void put_ctext(Window win, int x, int y, const char* s, int opaque)
  719. { int h = text_height(s);
  720.   int w = text_width(s);
  721.   put_text(win,x-w/2,y-h/2,s,opaque);
  722. }
  723. char* create_pixrect(Window win, int x1, int y1, int x2, int y2)
  724. { return 0; }
  725. void insert_pixrect(Window win, int x, int y, char* rect)
  726. {}
  727. void delete_pixrect(char* rect)
  728. {}
  729. void copy_pixrect(Window win, int x1, int y1, int x2, int y2, int x, int y)
  730. {}
  731. void insert_bitmap(Window win, int width, int height, char* data)
  732. {}
  733. void show_coordinates(Window win, const char* s)
  734. { int col = set_color(black);
  735.   int mode = set_mode(src_mode);
  736.   put_text(win,window_width(win)-120,0,s,1); 
  737.   set_mode(mode);
  738.   set_color(col);
  739.  }
  740. /* fonts and text */
  741. int  load_text_font(const char* font_name) { return 0; }
  742. int  load_bold_font(const char* font_name) { return 0; }
  743. int  load_message_font(const char* font_name) { return 0; }
  744. int  set_font(const char* fname) { return 0; }
  745. void set_text_font(void)
  746. { for(int win=1; win <=wcount; win++)
  747.   { HPS hps = wlist[win].hps_mem;
  748.     GpiCreateLogFont(hps,(PSTR8)NULL,TEXT_FONT_ID,&TextFattrs);
  749.     GpiSetCharSet(hps,TEXT_FONT_ID);
  750.     GpiQueryFontMetrics(hps,sizeof(FONTMETRICS),(PFONTMETRICS)&FontMetrics);
  751.    }
  752. }
  753. void set_bold_font(void)
  754. { for(int win=1; win <=wcount; win++)
  755.   { HPS hps = wlist[win].hps_mem;
  756.     GpiCreateLogFont(hps,(PSTR8)NULL,TEXT_FONT_ID,&TextFattrs);
  757.     GpiSetCharSet(hps,TEXT_FONT_ID);
  758.     GpiQueryFontMetrics(hps,sizeof(FONTMETRICS),(PFONTMETRICS)&FontMetrics);
  759.    }
  760. }
  761. void set_message_font(void)
  762. { for(int win=1; win <=wcount; win++)
  763.   { HPS hps = wlist[win].hps_mem;
  764.     GpiCreateLogFont(hps,(PSTR8)NULL,BOLD_FONT_ID,&BoldFattrs);
  765.     GpiSetCharSet(hps,BOLD_FONT_ID);
  766.     GpiQueryFontMetrics(hps,sizeof(FONTMETRICS),(PFONTMETRICS)&FontMetrics);
  767.    }
  768. }
  769. int text_width(const char* s)
  770. { return  strlen(s) * FontMetrics.lAveCharWidth; }
  771. int text_height(const char* s) 
  772. { return  FontMetrics.lMaxBaselineExt; }
  773. /* drawing parameters */
  774. int set_color(int col) 
  775. { int c = GCOLOR;
  776.   for(int win=1; win <=wcount; win++)
  777.   GpiSetColor(wlist[win].hps_mem,color_table[col]); 
  778.   GCOLOR = col;
  779.   return c;
  780.  }
  781. int set_mode(int mod) 
  782. { int m = MODE;
  783.   for(int win=1; win <=wcount; win++)
  784.      GpiSetMix(wlist[win].hps_mem,mode_table[mod]); 
  785.   if (mod == xor_mode) // switch to complementary colors
  786.   { 
  787.     color_table = color_table_xor;
  788.    }
  789.   else
  790.     color_table = color_table_src;
  791.   MODE = mod;
  792.   return m;
  793.  }
  794. int set_line_width(int w) 
  795. { int lw = LWIDTH;
  796.   for(int win=1; win <=wcount; win++)
  797.      GpiSetLineWidthGeom(wlist[win].hps_mem,w); 
  798.   LWIDTH = w;
  799.   return lw;
  800.  }
  801. int set_line_style(int s)
  802. { int ls = LSTYLE;
  803.   for(int win=1; win <=wcount; win++)
  804.   GpiSetLineType(wlist[win].hps_mem,lstyle_table[s]);
  805.   LSTYLE = s;
  806.   return ls;
  807.  }
  808. void set_read_gc()
  809. { for(int win=1; win <=wcount; win++)
  810.   { HPS hps = wlist[win].hps_mem;
  811.     GpiSetMix(hps,FM_XOR);
  812.     GpiSetColor(hps,color_table[black]);
  813.     GpiSetLineType(hps,LINETYPE_SOLID);
  814.     GpiSetLineWidthGeom(hps,1);
  815.    }
  816.  }
  817. void reset_gc()
  818. { for(int win=1; win <=wcount; win++)
  819.   { HPS hps = wlist[win].hps_mem;
  820.     GpiSetMix(hps,mode_table[MODE]);
  821.     GpiSetColor(hps,color_table[black]);
  822.     GpiSetLineType(hps,lstyle_table[LSTYLE]);
  823.     GpiSetLineWidthGeom(hps,LWIDTH);
  824.   }
  825. }
  826. /* colors */
  827. void set_palette(int i, int r, int g, int b)
  828. { unsigned char R = (unsigned char)r;
  829.   unsigned char G = (unsigned char)g;
  830.   unsigned char B = (unsigned char)b;
  831.   rgb_table[2*i+1] = LONGFromRGB(R,G,B);
  832.   for(int win=1; win<=wcount; win++)
  833.     GpiCreateLogColorTable(wlist[win].hps_mem,LCOL_PURECOLOR,
  834.                                               LCOLF_INDRGB,0L,32L,rgb_table);
  835. }
  836. int  new_color(const char*) { return black; }
  837. /* events */
  838. static QMSG qmsg;
  839. static int putback = 0;
  840. static event old_event;
  841. int  get_next_event(Window* win, int* val, int* x, int* y, unsigned long *t)
  842.   if (putback) 
  843.    { cur_event = old_event;
  844.      putback = 0;
  845.     }
  846.   else
  847.     { WinGetMsg (hab, &qmsg, 0L, 0, 0);
  848.       cur_event.kind = -1;
  849.       WinDispatchMsg (hab, &qmsg);
  850.       cur_event.t = qmsg.time;
  851.       if (cur_event.kind != -1) old_event = cur_event;
  852.      } 
  853.   *win = cur_event.win;
  854.   *val = cur_event.val;
  855.   *x   = cur_event.x;
  856.   *y   = cur_event.y;
  857.   *t   = cur_event.t;
  858.   return cur_event.kind;
  859.  }
  860. int  check_next_event(Window* win, int* val, int* x, int* y, unsigned long *t)
  861.   if (putback || WinPeekMsg(hab, &qmsg, 0L, 0, 0, PM_NOREMOVE))
  862.      return get_next_event(win,val,x,y,t); 
  863.   else
  864.      return no_event;
  865.  }
  866. void put_back_event(void) {  putback = 1; }