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

MultiPlatform

  1. /*******************************************************************************
  2. +
  3. +  LEDA-R  3.2.3
  4. +
  5. +  _vga.c
  6. +
  7. +  Copyright (c) 1995  by  Max-Planck-Institut fuer Informatik
  8. +  Im Stadtwald, 66123 Saarbruecken, Germany     
  9. +  All rights reserved.
  10. *******************************************************************************/
  11. #include <LEDA/impl/doswin.h>
  12. /* 
  13.  * basic graphics routines in VGA mode 640x480x16
  14.  * (part of this code is based on "VGAlib" by Tommy Frandsen)
  15.  */
  16. #if defined(__EMX__)
  17. #include <sys/hw.h>
  18. #define port_out(value,port) _outp32(port,value)
  19. #define port_in(port)  _inp32(port)
  20. #else
  21. #if defined(__TURBOC__) || defined(__GNUG__)
  22. #define port_out(value,port) outportb(port,value)
  23. #define port_in(port)  inportb(port)
  24. #else
  25. #define port_out(value,port) outp(port,value)
  26. #define port_in(port)  inp(port)
  27. #endif
  28. #endif
  29. #if defined (__ZTC__) || defined(__TURBOC__)
  30. typedef unsigned char far* VIDEO_PTR;
  31. #else
  32. typedef unsigned char* VIDEO_PTR;
  33. #endif
  34. static VIDEO_PTR  VIDEO=0;
  35. static int LINE_BYTES = 80;
  36. #define FONT_SIZE  0x2000
  37. /* VGA index register ports */
  38. #define CRT_IC  0x3D4   /* CRT Controller Index - color emulation */
  39. #define CRT_IM  0x3B4   /* CRT Controller Index - mono emulation */
  40. #define ATT_IW  0x3C0   /* Attribute Controller Index & Data Write Register */
  41. #define GRA_I   0x3CE   /* Graphics Controller Index */
  42. #define SEQ_I   0x3C4   /* Sequencer Index */
  43. #define PEL_IW  0x3C8   /* PEL Write Index */
  44. #define PEL_IR  0x3C7   /* PEL Read Index */
  45. /* VGA data register ports */
  46. #define CRT_DC  0x3D5   /* CRT Controller Data Register - color emulation */
  47. #define CRT_DM  0x3B5   /* CRT Controller Data Register - mono emulation */
  48. #define ATT_R   0x3C1   /* Attribute Controller Data Read Register */
  49. #define GRA_D   0x3CF   /* Graphics Controller Data Register */
  50. #define SEQ_D   0x3C5   /* Sequencer Data Register */
  51. #define MIS_R   0x3CC   /* Misc Output Read Register */
  52. #define MIS_W   0x3C2   /* Misc Output Write Register */
  53. #define IS1_RC  0x3DA   /* Input Status Register 1 - color emulation */
  54. #define IS1_RM  0x3BA   /* Input Status Register 1 - mono emulation */
  55. #define PEL_D   0x3C9   /* PEL Data Register */
  56. /* VGA indexes max counts */
  57. #define CRT_C   24      /* 24 CRT Controller Registers */
  58. #define ATT_C   21      /* 21 Attribute Controller Registers */
  59. #define GRA_C   9       /* 9  Graphics Controller Registers */
  60. #define SEQ_C   5       /* 5  Sequencer Registers */
  61. #define MIS_C   1       /* 1  Misc Output Register */
  62. /* VGA registers saving indexes */
  63. #define CRT     0               /* CRT Controller Registers start */
  64. #define ATT     CRT+CRT_C       /* Attribute Controller Registers start */
  65. #define GRA     ATT+ATT_C       /* Graphics Controller Registers start */
  66. #define SEQ     GRA+GRA_C       /* Sequencer Registers */
  67. #define MIS     SEQ+SEQ_C       /* General Registers */
  68. #define END     MIS+MIS_C       /* last */
  69. /* variables used to shift between monchrome and color emulation */
  70. static int CRT_I; /* current CRT index register address */
  71. static int CRT_D; /* current CRT data register address */
  72. static int IS1_R; /* current input status register address */
  73. static int color_text; /* true if color text emulation */
  74. /* BIOS mode 12h - 640x480x16 */
  75. static char g640x480x16_regs[60] = {
  76.   0x5F,0x4F,0x50,0x82,0x54,0x80,0x0B,0x3E,0x00,0x40,0x00,0x00,
  77.   0x00,0x00,0x00,0x00,0xEA,0x8C,0xDF,0x28,0x00,0xE7,0x04,0xE3,
  78.   0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,
  79.   0x0C,0x0D,0x0E,0x0F,0x01,0x00,0x0F,0x00,0x00,
  80.   0x00,0x0F,0x00,0x20,0x00,0x00,0x05,0x0F,0xFF,
  81.   0x03,0x01,0x0F,0x00,0x06,
  82.   0xE3
  83. };
  84. static char text_regs[60];   /* VGA registers for saved text mode */
  85. /* saved text mode palette values */
  86. static char text_red[256];
  87. static char text_green[256];
  88. static char text_blue[256];
  89. static int initialized = 0;
  90. static char font_buf1[FONT_SIZE];  /* saved font data - plane 2 */
  91. static char font_buf2[FONT_SIZE];  /* saved font data - plane 3 */
  92. static void set_regs(char regs[])
  93. {
  94.     int i;
  95.     /* disable video */
  96.     port_in(IS1_R);
  97.     port_out(0x00, ATT_IW);
  98.     /* update misc output register */
  99.     port_out(regs[MIS], MIS_W);
  100.     /* synchronous reset on */
  101.     port_out(0x00,SEQ_I);
  102.     port_out(0x01,SEQ_D);
  103.     /* write sequencer registers */
  104.     for (i = 1; i < SEQ_C; i++) {
  105. port_out(i, SEQ_I);
  106. port_out(regs[SEQ+i], SEQ_D);
  107.     }
  108.     /* synchronous reset off */
  109.     port_out(0x00, SEQ_I);
  110.     port_out(0x03, SEQ_D);
  111.     /* deprotect CRT registers 0-7 */
  112.     port_out(0x11, CRT_I);
  113.     port_out(port_in(CRT_D)&0x7F, CRT_D);
  114.     /* write CRT registers */
  115.     for (i = 0; i < CRT_C; i++) {
  116. port_out(i, CRT_I);
  117. port_out(regs[CRT+i], CRT_D);
  118.     }
  119.     /* write graphics controller registers */
  120.     for (i = 0; i < GRA_C; i++) {
  121. port_out(i, GRA_I);
  122. port_out(regs[GRA+i], GRA_D);
  123.     }
  124.     /* write attribute controller registers */
  125.     for (i = 0; i < ATT_C; i++) {
  126. port_in(IS1_R);   /* reset flip-flop */
  127. port_out(i, ATT_IW);
  128. port_out(regs[ATT+i],ATT_IW);
  129.     }
  130. }
  131. static void vga_initialize()
  132. {
  133.     int  i, j;
  134.     int mem_fd = -1;  /* /dev/mem file descriptor      */
  135.     if (initialized) return;
  136.     initialized = 1;
  137. #if defined(__EMX__)
  138.     _portaccess(0x300,0x3FF);
  139.     VIDEO = (VIDEO_PTR)_memaccess(0xa0000,0xaffff,1);
  140. #elif defined(__GNUC__)
  141.     VIDEO = (VIDEO_PTR)0xd0000000;
  142. #elif defined(__ZTC__)
  143.     VIDEO = (VIDEO_PTR)_x386_mk_protected_ptr(0xa0000);
  144. #elif defined(__WATCOMC__)
  145.     VIDEO = (VIDEO_PTR)0xa0000;
  146. #else
  147.     VIDEO = (VIDEO_PTR)MK_FP(0xa000,0);
  148. #endif
  149.     /* color or monochrome text emulation? */
  150.     color_text = port_in(MIS_R)&0x01;
  151.     /* chose registers for color/monochrome emulation */
  152.     if (color_text) {
  153. CRT_I = CRT_IC;
  154. CRT_D = CRT_DC;
  155. IS1_R = IS1_RC;
  156.     } else {
  157. CRT_I = CRT_IM;
  158. CRT_D = CRT_DM;
  159. IS1_R = IS1_RM;
  160.     }
  161.     /* disable video */
  162.     port_in(IS1_R);
  163.     port_out(0x00, ATT_IW);
  164.     /* save text mode palette - first select palette index 0 */
  165.     port_out(0, PEL_IR);
  166.     /* read RGB components - index is autoincremented */
  167.     for(i = 0; i < 256; i++) {
  168. for(j = 0; j < 10; j++) ;   /* delay (minimum 240ns) */
  169. text_red[i] = port_in(PEL_D);
  170. for(j = 0; j < 10; j++) ;   /* delay (minimum 240ns) */
  171. text_green[i] = port_in(PEL_D);
  172. for(j = 0; j < 10; j++) ;   /* delay (minimum 240ns) */
  173. text_blue[i] = port_in(PEL_D);
  174.     }
  175.     /* save text mode VGA registers */
  176.     for (i = 0; i < CRT_C; i++) {
  177.  port_out(i, CRT_I);
  178.  text_regs[CRT+i] = port_in(CRT_D);
  179.     }
  180.     for (i = 0; i < ATT_C; i++) {
  181.         port_in(IS1_R);
  182.          port_out(i, ATT_IW);
  183.          text_regs[ATT+i] = port_in(ATT_R);
  184.     }
  185.     for (i = 0; i < GRA_C; i++) {
  186.          port_out(i, GRA_I);
  187.          text_regs[GRA+i] = port_in(GRA_D);
  188.     }
  189.     for (i = 0; i < SEQ_C; i++) {
  190.          port_out(i, SEQ_I);
  191.          text_regs[SEQ+i] = port_in(SEQ_D);
  192.     }
  193.     text_regs[MIS] = port_in(MIS_R);
  194.     /* shift to color emulation */
  195.     CRT_I = CRT_IC;
  196.     CRT_D = CRT_DC;
  197.     IS1_R = IS1_RC;
  198.     port_out(port_in(MIS_R)|0x01, MIS_W);
  199.     /* save font data - first select a 16 color graphics mode */
  200.     set_regs(g640x480x16_regs);
  201.     /* save font data in plane 2 */
  202.     port_out(0x04, GRA_I);
  203.     port_out(0x02, GRA_D);
  204.     for(i = 0; i < FONT_SIZE; i++) font_buf1[i] = VIDEO[i];
  205.     /* save font data in plane 3 */
  206.     port_out(0x04, GRA_I);
  207.     port_out(0x03, GRA_D);
  208.     for(i = 0; i < FONT_SIZE; i++) font_buf2[i] = VIDEO[i];
  209. }
  210. void set_palette(int index, int red, int green, int blue)
  211. {
  212.     volatile int i;
  213.     if (red < 0)     red = _R_[index]; else _R_[index] = red;
  214.     if (green < 0) green = _G_[index]; else _G_[index] = green;
  215.     if (blue < 0)   blue = _B_[index]; else _B_[index] = blue;
  216.     /* select palette register */
  217.     port_out(index, PEL_IW);
  218.     /* write RGB components */
  219.     for(i = 0; i < 10; i++) ;   /* delay (minimum 240ns) */
  220.     port_out(red, PEL_D);
  221.     for(i = 0; i < 10; i++) ;   /* delay (minimum 240ns) */
  222.     port_out(green, PEL_D);
  223.     for(i = 0; i < 10; i++) ;   /* delay (minimum 240ns) */
  224.     port_out(blue, PEL_D);
  225. }
  226. void get_palette(int index, int *red, int *green, int *blue)
  227. {
  228.     int i;
  229.     /* select palette register */
  230.     port_out(index, PEL_IR);
  231.     /* read RGB components */
  232.     for(i = 0; i < 10; i++) ;   /* delay (minimum 240ns) */
  233.     *red = (int) port_in(PEL_D);
  234.     for(i = 0; i < 10; i++) ;   /* delay (minimum 240ns) */
  235.     *green = (int) port_in(PEL_D);
  236.     for(i = 0; i < 10; i++) ;   /* delay (minimum 240ns) */
  237.     *blue = (int) port_in(PEL_D);
  238. }
  239. static void vga_clear(int c)
  240. {
  241.   register VIDEO_PTR p;
  242.   register VIDEO_PTR last;
  243.   /* set color c */
  244.   port_out(c, GRA_I );
  245.   port_out(0, GRA_D );
  246.   /* set mode 0 */
  247.   port_out(0x03, GRA_I );
  248.   port_out(0, GRA_D );
  249.   /* write to all bits */
  250.   port_out(0x08, GRA_I );
  251.   port_out(0xFF, GRA_D );
  252.   last  = VIDEO + DISP_HEIGHT*LINE_BYTES;
  253.   for(p = VIDEO; p < last; p++)  *p = 0;
  254. }
  255. void init_graphics(int mode, int root_col)  // mode = 0: Text, 1: 640x480x16 
  256. {
  257.     int i;
  258.     vga_initialize();
  259.     
  260.     if (mode == 0)  // TEXT
  261.       { 
  262.         vga_clear(0);
  263.         /* restore font data - first select a 16 color graphics mode */
  264.         set_regs(g640x480x16_regs);
  265. /* disable Set/Reset Register */
  266.      port_out(0x01, GRA_I );
  267.      port_out(0x00, GRA_D );
  268.         /* restore font data in plane 2 - necessary for all VGA's */
  269.      port_out(0x02, SEQ_I );
  270.      port_out(0x04, SEQ_D );
  271.         for(i = 0; i < FONT_SIZE; i++) VIDEO[i] = font_buf1[i];
  272.         /* restore font data in plane 3 - necessary for Trident VGA's */
  273.      port_out(0x02, SEQ_I );
  274.      port_out(0x08, SEQ_D );
  275.         for(i = 0; i < FONT_SIZE; i++) VIDEO[i] = font_buf2[i];
  276.         /* change register adresses if monochrome text mode */
  277.         if (!color_text) {
  278.             CRT_I = CRT_IM;
  279.             CRT_D = CRT_DM;
  280.             IS1_R = IS1_RM;
  281.             port_out(port_in(MIS_R)&0xFE, MIS_W);
  282.         }
  283. /* restore text mode VGA registers */
  284.      set_regs(text_regs);
  285.         /* restore saved palette */
  286.         for(i = 0; i < 256; i++)
  287.             set_palette(i, text_red[i], text_green[i], text_blue[i]);
  288.         DISP_WIDTH = 80;
  289.         DISP_MAX_X = 79;
  290.         DISP_HEIGHT= 25;
  291.         DISP_MAX_Y = 24;
  292.       }
  293.     else // graphics mode
  294.       { 
  295.         /* shift to color emulation */
  296.         CRT_I = CRT_IC;
  297.         CRT_D = CRT_DC;
  298.         IS1_R = IS1_RC;
  299.         port_out(port_in(MIS_R)|0x01, MIS_W);
  300.         set_regs(g640x480x16_regs);
  301.         /* set default palette */
  302.         for(i = 0; i < 16; i++)
  303.           set_palette(i, _R_[i], _G_[i], _B_[i]);
  304.         vga_clear(root_col);
  305.         LINE_BYTES = 80;
  306.         DISP_WIDTH = 640;
  307.         DISP_MAX_X = 639;
  308.         DISP_HEIGHT= 480;
  309.         DISP_MAX_Y = 479;
  310.         DISP_DEPTH = 4;
  311.       }
  312.     /* enable video */
  313.     port_in(IS1_R);
  314.     port_out(0x20, ATT_IW);
  315.     if (mode == 0)  // TEXT
  316.     { union REGISTERS regs;
  317.       regs.h.ah=0x00;
  318.       regs.h.al=0x02;
  319.       int_86(0x10,&regs,&regs);
  320.     }
  321. }
  322. //------------------------------------------------------------------------------
  323. //  basic graphic routines of libWx  declared in <LEDA/impl/x_basic.h>) 
  324. //  iplemented for MSDOS using the VGA 640x480x16 color graphics mode
  325. //------------------------------------------------------------------------------
  326. #if !defined(M_PI)
  327. #define M_PI   3.14159265358979323846
  328. #endif
  329. static VIDEO_PTR video_buf;
  330. static int COLOR = 1;
  331. static int MODE  = 0;
  332. static int LINEWIDTH = 1;
  333. static int LINESTYLE = 0;
  334. void flush_display() {}
  335. int  new_color(const char*) { return 1; }
  336. int  text_height(const char*)  { return FONT_HEIGHT; }
  337. int  text_width(const char* s) { return FONT_WIDTH*strlen(s); }
  338. int load_text_font(const char*) { return 0;}
  339. int load_bold_font(const char*) { return 0;}
  340. int load_message_font(const char*) { return 0;}
  341. int  set_font(const char*) { return 0;}
  342. void set_text_font() {}
  343. void set_bold_font() {}
  344. void set_message_font() {}
  345. int set_line_width(int width)
  346. { int save = LINEWIDTH;
  347.   LINEWIDTH = width;
  348.   return save;
  349. }
  350. int set_line_style(int style)
  351. { int save = LINESTYLE;
  352.   LINESTYLE = style;
  353.   return save;
  354. }
  355. int set_color(int color)
  356. {  int save = COLOR;
  357.    COLOR = color;
  358.    port_out(0x00, GRA_I );
  359.    port_out(color, GRA_D );
  360.    return save;
  361.  }
  362. int set_mode(int mode)
  363. { int save = MODE;
  364.   MODE = mode;
  365.   if (mode==1)         mode = 3; /* xor */
  366.   else if (mode==2)    mode = 2; /* or  */
  367.      else if (mode==3) mode = 1; /* and */
  368.                   else mode = 0; /* src */
  369.   port_out(0x03, GRA_I );
  370.   port_out(mode<<3, GRA_D );
  371.   return save;
  372. }
  373. void set_redraw(Window w, void (*f)())
  374. { win_stack[w]->redraw = f; }
  375. static void put_pixel(DosWindow win, int x, int y)
  376. { VIDEO_PTR p;
  377.   if (x < 0 || x >= win->width || y < 0 || y >= win->height) return;
  378.   x += win->xpos;
  379.   y += win->ypos;
  380.   if (x < 0 || x > DISP_MAX_X || y < 0 || y > DISP_MAX_Y) return;
  381.   if (VIDEO==0)   /* write into (monochrome) buffer */
  382.      video_buf[y*LINE_BYTES+(x>>3)] |= (0x80 >> (x & 7));
  383.   else
  384.   { p = VIDEO + y*LINE_BYTES + (x>>3);
  385.     port_out(8, GRA_I);
  386.     port_out((0x80 >> (x & 7)), GRA_D);
  387.     *p = *p;
  388.    }
  389. }
  390. static void vline(DosWindow win,int x, int y0, int y1)
  391. { register VIDEO_PTR p;
  392.   register VIDEO_PTR last;
  393.   if (y0 > y1)
  394.   { int y = y0;
  395.     y0 = y1;
  396.     y1 = y;
  397.    }
  398.   // clip into window
  399.   if (x < 0 || x >= win->width || y1 < 0 || y0 >= win->height) return;
  400.   if (y0 < 0) y0 = 0;
  401.   if (y1 >= win->height) y1 = win->height-1;
  402.   x  += win->xpos;
  403.   y0 += win->ypos;
  404.   y1 += win->ypos;
  405.   // clip into screen
  406.   if (x < 0 || x > DISP_MAX_X || y1 < 0 || y0 > DISP_MAX_Y) return;
  407.   if (y0 < 0) y0 = 0;
  408.   if (y1 > DISP_MAX_Y) y1 = DISP_MAX_Y;
  409.   port_out(8, GRA_I);
  410.   port_out(128 >> (x&7), GRA_D);
  411.   last  = VIDEO + LINE_BYTES*y1 + (x>>3);
  412.   for(p = VIDEO + LINE_BYTES*y0 + (x>>3); p <= last; p+=LINE_BYTES)  *p = *p;
  413. }
  414. static void hline(DosWindow win, int x0, int x1, int y)
  415. { register VIDEO_PTR p;
  416.   register VIDEO_PTR first;
  417.   register VIDEO_PTR last;
  418.   char byte;
  419.   if (x0 > x1)
  420.   { int x = x0;
  421.     x0 = x1;
  422.     x1 = x;
  423.    }
  424.   // clip into window
  425.   if (y < 0 || y >= win->height || x1 < 0 || x0 >= win->width) return;
  426.   if (x0 < 0) x0 = 0;
  427.   if (x1 >= win->width) x1 = win->width-1;
  428.   x0 += win->xpos;
  429.   x1 += win->xpos;
  430.   y  += win->ypos;
  431.   // clip into screen
  432.   if (y < 0 || y > DISP_MAX_Y || x1 < 0 || x0 > DISP_MAX_X) return;
  433.   if (x0 < 0) x0 = 0;
  434.   if (x1 > DISP_MAX_X) x1 = DISP_MAX_X;
  435.   first = VIDEO + LINE_BYTES*y + (x0>>3);
  436.   last  = VIDEO + LINE_BYTES*y + (x1>>3);
  437.   port_out(8, GRA_I);
  438.   if (first == last)
  439.   { byte  = 0xFF>>(x0&7);
  440.     byte &= 0xFF<<((~x1)&7);
  441.     port_out(byte, GRA_D);
  442.     *first = *first;
  443.     return;
  444.    }
  445.   port_out(0xFF>>(x0&7), GRA_D);
  446.   *first = *first;
  447.   port_out(0xFF<<((~x1)&7), GRA_D);
  448.   *last = *last;
  449.   port_out(0xFF, GRA_D);
  450.   for(p=first+1; p<last; p++) *p = *p;
  451.  }
  452. static void Draw_Line(DosWindow win, int x1, int y1, int x2, int y2)
  453. {
  454.   register int sy = 1;
  455.   register int dx = x2 - x1;
  456.   register int dy = y2 - y1;
  457.   register int c;
  458.   int i;
  459.   if (dx < 0)
  460.   { int i = x1;
  461.     x1 = x2;
  462.     x2 = i;
  463.     dx = -dx;
  464.     i = y1;
  465.     y1 = y2;
  466.     y2 = i;
  467.     dy = -dy;
  468.    }
  469.   if (dy < 0)
  470.   { dy = -dy;
  471.     sy = -1;
  472.    }
  473.   if (dx > dy)
  474.   { c = dx / 2;
  475.     put_pixel(win,x1,y1);
  476.     for (i=1; i<=LINEWIDTH/2; i++)
  477.     { put_pixel(win,x1,y1+i);
  478.       put_pixel(win,x1,y1-i);
  479.      }
  480.     while(x1 != x2)
  481.     { x1++;
  482.       c += dy;
  483.       if (c >= dx)
  484.       { c -= dx;
  485.         y1 += sy;
  486.        }
  487.       put_pixel(win,x1,y1);
  488.       for (i=1; i<=LINEWIDTH/2; i++)
  489.       { put_pixel(win,x1,y1+i);
  490.         put_pixel(win,x1,y1-i);
  491.        }
  492.     }
  493.   }
  494.   else
  495.   { c = dy / 2;
  496.     put_pixel(win,x1,y1);
  497.     for (i=1; i<=LINEWIDTH/2; i++)
  498.     { put_pixel(win,x1+i,y1);
  499.       put_pixel(win,x1-i,y1);
  500.      }
  501.     while(y1 != y2)
  502.     { y1 += sy;
  503.       c += dx;
  504.       if (c >= dy)
  505.       { c -= dy;
  506.         x1++;
  507.        }
  508.       put_pixel(win,x1,y1);
  509.       for (i=1; i<=LINEWIDTH/2; i++)
  510.       { put_pixel(win,x1+i,y1);
  511.         put_pixel(win,x1-i,y1);
  512.        }
  513.     }
  514.   }
  515. }
  516. void line(Window w, int x1, int y1, int x2, int y2)
  517. { int i;
  518.   DosWindow win = win_stack[w];
  519.   if (x1 == x2)
  520.   { vline(win,x1,y1,y2);
  521.     for (i=1; i<=LINEWIDTH/2; i++)
  522.     { vline(win,x1-i,y1,y2);
  523.       vline(win,x1+i,y1,y2);
  524.      }
  525.     return;
  526.    }
  527.   if (y1 == y2)
  528.   { hline(win,x1,x2,y1);
  529.     for (i=1; i<=LINEWIDTH/2; i++)
  530.     { hline(win,x1,x2,y1-i);
  531.       hline(win,x1,x2,y1+i);
  532.      }
  533.     return;
  534.    }
  535.   Draw_Line(win,x1,y1,x2,y2);
  536. }
  537. static int get_pixel(int x, int y)
  538. {
  539.   register int bit = 0x80 >> (x&7);
  540.   register VIDEO_PTR byte = VIDEO + LINE_BYTES*y+(x>>3);
  541.   register int c;
  542.   if (x < 0 || x > DISP_MAX_X || y < 0 || y > DISP_MAX_Y) return 0;
  543.   /* set read mode 1 */
  544.   port_out(5, GRA_I);
  545.   port_out(8, GRA_D);
  546.   for(c=0; c<16; c++)
  547.   { port_out(2, GRA_I);
  548.     port_out(c, GRA_D);
  549.     if (*byte & bit)  break;
  550.    }
  551.   return c;
  552. }
  553. #define FILLPUT(pos,byte)
  554. { p = pos;
  555.   if ((*p & (byte)) == 0)
  556.   { *p |= (byte);
  557.     POS[top] = p; 
  558.     BYTE[top] = byte; 
  559.     top = (top+1) % 512; } else;
  560. }
  561. static  VIDEO_PTR      POS[512];
  562. static  unsigned char  BYTE[512];
  563. static void fill_bits(VIDEO_PTR pos,unsigned char byte)
  564. { register int bot = 0;
  565.   register int top = 0;
  566.   register VIDEO_PTR p;
  567.   FILLPUT(pos,byte)
  568.   while (top != bot)
  569.   { pos  = POS[bot];
  570.     byte = BYTE[bot];
  571.     bot = (bot+1) % 512;
  572.     if (byte == 128)
  573.        FILLPUT(pos-1,1)
  574.     else
  575.        FILLPUT(pos,byte<<1)
  576.     if (byte == 1)
  577.        FILLPUT(pos+1,128)
  578.     else
  579.        FILLPUT(pos,byte>>1)
  580.     FILLPUT(pos-LINE_BYTES,byte)
  581.     FILLPUT(pos+LINE_BYTES,byte)
  582.   }
  583. }
  584. static  VIDEO_PTR  POS1[512];
  585. static  int pos_top = 0;
  586. void fill_bytes(VIDEO_PTR pos, int d)
  587. { VIDEO_PTR p = pos+d;
  588.   unsigned char c = *p;
  589.   unsigned char pat = 0xFF;
  590.   if (c == 0)
  591.   { *p = 0xFF;
  592.     fill_bytes(p,  1);
  593.     fill_bytes(p, -1);
  594.     fill_bytes(p, LINE_BYTES);
  595.     fill_bytes(p,-LINE_BYTES);
  596.     return;
  597.    }
  598.   if (d == -1)
  599.   { while((c&1) == 0)
  600.     { pat <<= 1;
  601.       c >>= 1;
  602.      }
  603.     *p |= ~pat;
  604.    }
  605.   if (d == 1)
  606.   { while((c&128) == 0)
  607.     { pat >>= 1;
  608.       c <<= 1;
  609.      }
  610.     *p |= ~pat;
  611.    }
  612.   if((c&8) == 0 && (d == LINE_BYTES || d == -LINE_BYTES))   POS1[pos_top++] = p;
  613.  }
  614. void fill_polygon(Window w, int n, int* xcoord, int* ycoord)
  615. {
  616.   DosWindow win = win_stack[w];
  617.   register VIDEO_PTR p;
  618.   register VIDEO_PTR q;
  619.   register VIDEO_PTR first;
  620.   register VIDEO_PTR first1;
  621.   register VIDEO_PTR last;
  622.   int i,m1,m2;
  623.   int minxi = 0;
  624.   int maxxi = 0;
  625.   int minyi = 0;
  626.   int maxyi = 0;
  627.   int minx,maxx,miny,maxy,x,y;
  628.   VIDEO_PTR video_save = VIDEO;
  629.   VIDEO = 0;
  630.   video_buf = (VIDEO_PTR)malloc(LINE_BYTES*480);
  631.   for(i=1;i<n;i++)
  632.   { minxi = (xcoord[i] < xcoord[minxi]) ? i : minxi;
  633.     minyi = (ycoord[i] < ycoord[minyi]) ? i : minyi;
  634.     maxxi = (xcoord[i] > xcoord[maxxi]) ? i : maxxi;
  635.     maxyi = (ycoord[i] > ycoord[maxyi]) ? i : maxyi;
  636.    }
  637.   minx = (xcoord[minxi] + win->xpos)/8;
  638.   maxx = (xcoord[maxxi] + win->xpos)/8;
  639.   miny = ycoord[minyi] + win->ypos;
  640.   maxy = ycoord[maxyi] + win->ypos;
  641.   m1 =  (minxi == 0)   ?  n-1 : minxi-1;
  642.   m2 =  (minxi == n-1) ?  0   : minxi+1;
  643.   for(i=miny; i<=maxy; i++)
  644.   { last = video_buf+LINE_BYTES*i + maxx;
  645.     for(p=video_buf+LINE_BYTES*i+minx; p<=last; p++) *p= 0;
  646.    }
  647.   for(i=0; i<n-1; i++)
  648.       Draw_Line(win,xcoord[i],ycoord[i],xcoord[i+1],ycoord[i+1]);
  649.   Draw_Line(win,xcoord[0],ycoord[0],xcoord[n-1],ycoord[n-1]);
  650.   x = (xcoord[m1] + xcoord[m2] + xcoord[minxi])/3 + win->xpos;
  651.   y = (ycoord[m1] + ycoord[m2] + ycoord[minxi])/3 + win->ypos;
  652.   pos_top = 0;
  653.   fill_bytes(video_buf + LINE_BYTES*y + x/8,0);
  654.   while (pos_top--) fill_bits(POS1[pos_top],8);
  655.   fill_bits(video_buf+LINE_BYTES*y+x/8,128>>(x%8));
  656.   VIDEO = video_save;
  657.   first  = video_buf+LINE_BYTES*miny + minx;
  658.   first1 = VIDEO+LINE_BYTES*miny + minx;
  659.   last   = video_buf+LINE_BYTES*miny + maxx;
  660.   port_out(8, GRA_I);
  661.   while(miny <= maxy)
  662.   { for(p=first, q = first1; p<=last; p++, q++)
  663.     { port_out(*p, GRA_D);
  664.       *q = *q;
  665.      }
  666.     first  += LINE_BYTES;
  667.     first1 += LINE_BYTES;
  668.     last   += LINE_BYTES;
  669.     miny++;
  670.    }
  671.   free((char*)video_buf);
  672. }
  673. void box(Window w, int x0, int y0, int x1, int y1)
  674. { DosWindow win = win_stack[w];
  675.   if (y0 > y1)
  676.   { int y = y0;
  677.     y0 = y1;
  678.     y1 = y;
  679.    }
  680.   while(y0<=y1) hline(win,x0,x1,y0++);
  681.  }
  682. void  rectangle(Window w, int x0, int y0, int x1, int y1)
  683.   int left  = x0;
  684.   int right = x1;
  685.   int top   = y0;
  686.   int bottom= y1;
  687.   if (x0 > x1)
  688.   { left  = x1;
  689.     right = x0;
  690.    }
  691.   if (y0 > y1)
  692.   { top  = y1;
  693.     bottom = y0;
  694.    }
  695.   line(w,left, top,     right,top);
  696.   line(w,left, bottom,  right,bottom);
  697.   line(w,left, bottom-1,left, top+1);
  698.   line(w,right,bottom-1,right,top+1);
  699. }
  700. void circle(Window w, int x0,int y0,int r0)
  701. { DosWindow win = win_stack[w];
  702.   int r;
  703.   for (r = r0-LINEWIDTH/2; r <= r0+LINEWIDTH/2; r++)
  704.   { int y = r;
  705.     int x = 0;
  706.     int e = 3-2*y;
  707.     put_pixel(win,x0,y0+r);
  708.     put_pixel(win,x0,y0-r);
  709.     put_pixel(win,x0+r,y0);
  710.     put_pixel(win,x0-r,y0);
  711.     for (x=1;x<y;)
  712.       { put_pixel(win,x0+x,y0+y);
  713.         put_pixel(win,x0+x,y0-y);
  714.         put_pixel(win,x0-x,y0+y);
  715.         put_pixel(win,x0-x,y0-y);
  716.         put_pixel(win,x0+y,y0+x);
  717.         put_pixel(win,x0+y,y0-x);
  718.         put_pixel(win,x0-y,y0+x);
  719.         put_pixel(win,x0-y,y0-x);
  720.         x++;
  721.         if (e>=0) { y--; e = e - 4*y; }
  722.         e = e + 4*x + 2;
  723.        }
  724.     if (x == y)
  725.     { put_pixel(win,x0+x,y0+y);
  726.       put_pixel(win,x0+x,y0-y);
  727.       put_pixel(win,x0-x,y0+y);
  728.       put_pixel(win,x0-x,y0-y);
  729.      }
  730.   }
  731. }
  732. void fill_circle(Window w, int x0, int y0, int r)
  733. { DosWindow win = win_stack[w];
  734.   int y = 1;
  735.   int x = r;
  736.   int e = 3-2*r;
  737.   hline(win,x0-x,x0+x,y0);
  738.   while (y<=x)
  739.   { hline(win,x0-x,x0+x,y0+y);
  740.     hline(win,x0-x,x0+x,y0-y);
  741.     if (y<x && e>=0)
  742.     { hline(win,x0-y,x0+y,y0+x);
  743.       hline(win,x0-y,x0+y,y0-x);
  744.       x--;
  745.       e = e - 4*x;
  746.      }
  747.     y++;
  748.     e = e + 4*y + 2;
  749.    }
  750. }
  751. static void Put_Text(DosWindow win, int x, int y, const char *str, int bg_col)
  752. { /* bgcol = -1 : transparent */
  753.   register unsigned char *fp1;
  754.   register unsigned char *fp2;
  755.   register unsigned char c;
  756.   register VIDEO_PTR start;
  757.   register VIDEO_PTR stop;
  758.   register VIDEO_PTR q;
  759.   char text[128];
  760.   int  len = strlen(str);
  761.   int xmin = win->xpos;
  762.   int ymin = win->ypos;
  763.   int xmax = xmin + win->width  - 1;
  764.   int ymax = ymin + win->height - 1;
  765.   if (xmin < 0) xmin = 0;
  766.   if (ymin < 0) ymin = 0;
  767.   if (xmax > DISP_MAX_X) xmax = DISP_MAX_X;
  768.   if (ymax > DISP_MAX_Y) ymax = DISP_MAX_Y;
  769.   if (bg_col >= 0)  // clear background
  770.   { int save_color = set_color(bg_col);
  771.     int save_mode = set_mode(0);
  772.     box(win->id,x,y,x+text_width(str)-1,y+FONT_HEIGHT-1);
  773.     set_mode(save_mode);
  774.     set_color(save_color);
  775.    }
  776.   x += win->xpos;
  777.   y += win->ypos;
  778.   if (y < ymin || y > ymax || x > xmax) return;  // string not visible
  779.   if (x < xmin) 
  780.   { int pre = (xmin - x)/FONT_WIDTH + 1;
  781.     if (pre >= len) return;
  782.     str += pre;
  783.     len -= pre;
  784.     x = xmin;
  785.   }
  786.   int maxlen = (xmax-x)/FONT_WIDTH;
  787.   if (len > maxlen) len = maxlen;
  788.   if (len > 0) strncpy(text,str,len);
  789.   text[len] = 0;
  790.   int dy = ymax - y;
  791.   if (dy > FONT_HEIGHT) dy = FONT_HEIGHT;
  792.   fp1 = FONT + FONT_HEIGHT * ' ';
  793.   fp2 = FONT + FONT_HEIGHT * (text[0] & 127);
  794.   start = VIDEO + LINE_BYTES*y + x/8;
  795.   stop = start + LINE_BYTES*dy;
  796.   x &= 7;
  797.   port_out(8, GRA_I);
  798.   for(int i=0;i<len; i++)
  799.   { for (q = start; q < stop; q+=LINE_BYTES, fp1++,fp2++)
  800.     { c = ((*fp2)>>x) | ((*fp1)<<(8-x));
  801.       port_out(c, GRA_D);
  802.       *q = *q;
  803.      }
  804.     fp1 = FONT + FONT_HEIGHT * (text[i] & 127);
  805.     fp2 = FONT + FONT_HEIGHT * (text[i+1] & 127);
  806.     start++;
  807.     stop++;
  808.    }
  809.   if (x > 0)
  810.     for (q = start; q < stop; q+=LINE_BYTES, fp1++,fp2++)
  811.     { c = (*fp1)<<(8-x);
  812.       port_out(c, GRA_D);
  813.       *q = *q;
  814.      }
  815. }
  816. void put_text(Window w, int x, int y, const char *text, int opaque)
  817. { DosWindow win = win_stack[w];
  818.   Put_Text(win,x,y,text,opaque ? win->bg_col : -1);
  819. }
  820. void put_text(Window w, int x, int y, const char *text, int l, int opaque)
  821. { DosWindow win = win_stack[w];
  822.   //char* str = new char[l+1];
  823.   //strncpy(str,text,l);
  824.   char* str = new char[strlen(text)+1];
  825.   strcpy(str,text);
  826.   str[l] = '';
  827.   Put_Text(win,x,y,str,opaque ? win->bg_col : -1); 
  828.   delete[] str;
  829. }
  830. void put_ctext(Window w, int x, int y, const char* str, int opaque)
  831. { put_text(w,x-(text_width(str)-1)/2, y-(text_height(str)-1)/2, str, opaque); }
  832. void show_coordinates(Window w, const char* s)
  833. { DosWindow win = win_stack[w];
  834.   int save_mode = set_mode(0);
  835.   int save_col  = set_color(4);
  836.   put_text(w,win->width-138,1,s,1); 
  837.   set_mode(save_mode);
  838.   set_color(save_col);
  839. }
  840. void pixel(Window w, int x, int y) { put_pixel(win_stack[w],x,y);}
  841. void pixels(Window w, int n, int* x, int* y)
  842. { while(n--) put_pixel(win_stack[w],x[n],y[n]); }
  843. void point(Window w, int x, int y) 
  844. { DosWindow win = win_stack[w];
  845.   put_pixel(win,x,y);
  846.   put_pixel(win,x-2,y-2);
  847.   put_pixel(win,x-1,y-1);
  848.   put_pixel(win,x+1,y+1);
  849.   put_pixel(win,x+2,y+2);
  850.   put_pixel(win,x-2,y+2);
  851.   put_pixel(win,x-1,y+1);
  852.   put_pixel(win,x+1,y-1);
  853.   put_pixel(win,x+2,y-2);
  854. }
  855. #define put_arc_pixel(X,Y,x,y,top) { X[top] = x; Y[top] = y; top++; }
  856. void arc(Window w, int x0, int y0, int r1, int r2, double start, double angle)
  857. { DosWindow win = win_stack[w];
  858.   int* X = new int[10*r1];
  859.   int* Y = new int[10*r2];
  860.   int r;
  861.  x0 += win->xpos;
  862.  y0 += win->ypos;
  863.  if (angle < 0)
  864.  { start += angle;
  865.    angle *= -1;
  866.   }
  867.  if (angle > 2*M_PI) angle = 2*M_PI;
  868.  while (start < 0) start += 2*M_PI;
  869.  for (r = r1-LINEWIDTH/2; r <= r1+LINEWIDTH/2; r++)
  870.  { int y = r;
  871.    int x = 0;
  872.    int e = 3-2*y;
  873.    int top = 0;
  874.    int high;
  875.    int high1;
  876.    int s,l;
  877.    float L;
  878.    int i;
  879.    while (x < y)
  880.    { put_arc_pixel(X,Y,x,y,top);
  881.      x++;
  882.      if (e>=0) { y--; e -= 4*y; }
  883.      e += 4*x + 2;
  884.     }
  885.    high = top-1;
  886.    if (x==y) put_arc_pixel(X,Y,x,y,top);
  887.    high1 = top;
  888.    for(i = 0;    i < high1; i++) put_arc_pixel(X,Y, Y[i],-X[i],top);
  889.    for(i = high; i > 0;     i--) put_arc_pixel(X,Y, X[i],-Y[i],top);
  890.    for(i = 0;    i < high1; i++) put_arc_pixel(X,Y,-X[i],-Y[i],top);
  891.    for(i = high; i > 0;     i--) put_arc_pixel(X,Y,-Y[i],-X[i],top);
  892.    for(i = 0;    i < high1; i++) put_arc_pixel(X,Y,-Y[i], X[i],top);
  893.    for(i = high; i > 0;     i--) put_arc_pixel(X,Y,-X[i], Y[i],top);
  894.    for(i = 0;    i < high1; i++) put_arc_pixel(X,Y, X[i], Y[i],top);
  895.    for(i = high; i > 0;     i--) put_arc_pixel(X,Y, Y[i], X[i],top);
  896.    L = (top - high1)/(2*M_PI);
  897.    s = high1 - 1 + (int)(start*L);
  898.    l = s + (int)(angle*L);
  899.    if (l >= top)
  900.    { for(i=s; i < top; i++) put_pixel(win,x0+X[i],y0+Y[i]);
  901.      s = high - 1;
  902.      l = s + l - top;
  903.     }
  904.    for(i=s; i < l; i++) put_pixel(win,x0+X[i],y0+Y[i]);
  905.   }
  906.   delete X;
  907.   delete Y;
  908. }
  909. static void ellipse_point(DosWindow win, int x0, int y0, int x, int y)
  910. { put_pixel(win,x0+x,y0+y);
  911.   put_pixel(win,x0-x,y0+y);
  912.   put_pixel(win,x0+x,y0-y);
  913.   put_pixel(win,x0-x,y0-y);
  914.  }
  915. void ellipse(Window w, int x0, int y0, int a, int b)
  916.   /* Foley, van Dam, Feiner, Huges: Computer Graphics, page 90 */
  917.   DosWindow win = win_stack[w];
  918.   double d1,d2;
  919.   int x,y;
  920.   int a_2 = a*a;
  921.   int b_2 = b*b;
  922.   put_pixel(win,x0,y0-b);
  923.   put_pixel(win,x0,y0+b);
  924.   put_pixel(win,x0-a,y0);
  925.   put_pixel(win,x0+a,y0);
  926.   x = 0;
  927.   y = b;
  928.   d1 = b*b + a*a*(0.25 - b); 
  929.    
  930.   while (a_2*(y - 0.5) > b_2*(x+1))
  931.   { if (d1 < 0)
  932.       d1 += b_2*(2*x + 3);
  933.     else
  934.     { d1 += b_2*(2*x + 3) + a_2*(2 - 2*y);
  935.       y--;
  936.      }
  937.     x++;
  938.     ellipse_point(win,x0,y0,x,y);
  939.   }
  940.   d2 = b_2*(x+0.5)*(x+0.5) + a_2*(y - 1)*(y - 1) - a_2*b_2;
  941.   while (y > 1)
  942.   { if (d2 < 0)
  943.      { d2 += b_2*(2*x+2)+a_2*(3-2*y);
  944.        x++;
  945.       }
  946.     else
  947.        d2 += a*a*(3-2*y);
  948.     y--;
  949.     ellipse_point(win,x0,y0,x,y);
  950.    }
  951. }
  952. void fill_ellipse(Window w, int x0, int y0, int a, int b)
  953. { DosWindow win = win_stack[w];
  954.   double d1,d2;
  955.   int x,y;
  956.   int a_2 = a*a;
  957.   int b_2 = b*b;
  958.   x = 0;
  959.   y = b;
  960.   d1 = b*b + a*a*(0.25 - b); 
  961.    
  962.   while (a_2*(y - 0.5) > b_2*(x+1))
  963.   { if (d1 < 0)
  964.       d1 += b_2*(2*x + 3);
  965.     else
  966.     { d1 += b_2*(2*x + 3) + a_2*(2 - 2*y);
  967.       hline(win,x0-x,x0+x,y0+y);
  968.       hline(win,x0-x,x0+x,y0-y);
  969.       y--;
  970.      }
  971.     x++;
  972.   }
  973.   hline(win,x0-x,x0+x,y0+y);
  974.   hline(win,x0-x,x0+x,y0-y);
  975.   d2 = b_2*(x+0.5)*(x+0.5) + a_2*(y - 1)*(y - 1) - a_2*b_2;
  976.   while (y > 1)
  977.   { if (d2 < 0)
  978.      { d2 += b_2*(2*x+2)+a_2*(3-2*y);
  979.        x++;
  980.       }
  981.     else
  982.        d2 += a*a*(3-2*y);
  983.     y--;
  984.     hline(win,x0-x,x0+x,y0+y);
  985.     hline(win,x0-x,x0+x,y0-y);
  986.    }
  987.   hline(win,x0-x,x0+x,y0);
  988. }
  989. void fill_arc(Window,int,int,int,int,double,double)
  990. { }
  991. void copy_pixrect(Window w,int left,int top,int right,int bottom,int x,int y)
  992.   DosWindow win = win_stack[w];
  993.   int width = right-left+1;
  994.   int height = bottom-top+1;
  995.   left += win->xpos; 
  996.   top  += win->ypos; 
  997.   x    += win->xpos; 
  998.   y    += win->ypos; 
  999.  
  1000.   register VIDEO_PTR first1;
  1001.   register VIDEO_PTR first;
  1002.   register VIDEO_PTR last1;
  1003.   register VIDEO_PTR last;
  1004.   register VIDEO_PTR p;
  1005.   register VIDEO_PTR q;
  1006.   int i;
  1007.   if(x < 0) 
  1008.   { left += x;
  1009.     width -= x;
  1010.     x = 0;
  1011.    }
  1012.   if(y < 0) 
  1013.   { top += y;
  1014.     height -= y;
  1015.     y = 0;
  1016.    }
  1017.   if(x+width > DISP_MAX_X) width = DISP_MAX_X - x;
  1018.   if(y+height > DISP_MAX_Y) height = DISP_MAX_Y - y;
  1019.   /* set write mode 1 */
  1020.   port_out(5, GRA_I);
  1021.   port_out(1, GRA_D);
  1022.   if (y <= top)
  1023.   { first1 = VIDEO + LINE_BYTES*y + x/8;
  1024.     last1  = VIDEO + LINE_BYTES*y + (x+width-1)/8;
  1025.     first  = VIDEO + LINE_BYTES*top + left/8;
  1026.     last   = VIDEO + LINE_BYTES*top + (left+width-1)/8;
  1027.    }
  1028.   else
  1029.   { first1 = VIDEO + LINE_BYTES*(y+height-1) + x/8;
  1030.     last1  = VIDEO + LINE_BYTES*(y+height-1) + (x+width-1)/8;
  1031.     first  = VIDEO + LINE_BYTES*(top+height-1) + left/8;
  1032.     last   = VIDEO + LINE_BYTES*(top+height-1) + (left+width-1)/8;
  1033.    }
  1034.   for(i=0; i<height; i++)
  1035.   { 
  1036.     if (x <= left)
  1037.       for(q=first, p=first1; q<=last; q++,p++) *p = *q;
  1038.     else
  1039.       for(q=last, p=last1; q>=first; q--,p--) *p = *q;
  1040.     if (y <= top)
  1041.     { first1 += LINE_BYTES;
  1042.       first  += LINE_BYTES;
  1043.       last1  += LINE_BYTES;
  1044.       last   += LINE_BYTES;
  1045.      }
  1046.     else
  1047.     { first1 -= LINE_BYTES;
  1048.       first  -= LINE_BYTES;
  1049.       last1  -= LINE_BYTES;
  1050.       last   -= LINE_BYTES;
  1051.      }
  1052.    }
  1053.   /* set write mode 0 */
  1054.   port_out(5, GRA_I);
  1055.   port_out(0, GRA_D);
  1056.  }
  1057. static char rev_byte(char c)
  1058. { char c1 = 0x00;
  1059.    for(int i=0; i<8; i++)
  1060.    { c1 <<= 1;
  1061.      if (c&1) c1 |= 1;
  1062.      c >>= 1;
  1063.     }
  1064.   return c1;
  1065. }
  1066. void insert_bitmap(Window w, int width, int height, char* data)
  1067. {
  1068.   register VIDEO_PTR first;
  1069.   register VIDEO_PTR last;
  1070.   register VIDEO_PTR q;
  1071.   DosWindow win = win_stack[w];
  1072.   int x = win->x0/8 + 1;
  1073.   int y = win->ypos;
  1074.   int wi = (width > win->width) ? win->width : width;
  1075.   int he = (height > win->height) ? win->height : height;
  1076.   first  = VIDEO + LINE_BYTES*y + x;
  1077.   last   = VIDEO + LINE_BYTES*y + x + wi/8 - 1;
  1078.   if (width % 8)
  1079.      width  = 1+ width/8;
  1080.   else
  1081.      width  = width/8;
  1082.   port_out(8, GRA_I);
  1083.   for(int i=0; i<he; i++)
  1084.   { char* p = data + i*width;
  1085.     for(q=first; q<=last; q++) 
  1086.     { port_out(rev_byte(*p++), GRA_D);
  1087.       *q = *q;
  1088.      }
  1089.     first += LINE_BYTES;
  1090.     last  += LINE_BYTES;
  1091.    }
  1092.  }
  1093. //------------------------------------------------------------------------------
  1094. // pixrects
  1095. //------------------------------------------------------------------------------
  1096. struct pixrect
  1097. { VIDEO_PTR plane[4];
  1098.   int width;
  1099.   int height;
  1100.   int bwidth;  // bytes
  1101. };
  1102. char* create_pixrect(Window w, int left, int top, int right, int bottom)
  1103.   DosWindow win = win_stack[w];
  1104.   int xmax = win->xpos + win->width - 1;
  1105.   int ymax = win->ypos + win->height - 1;
  1106.   register int y;
  1107.   register VIDEO_PTR p;
  1108.   register VIDEO_PTR q;
  1109.   register VIDEO_PTR first;
  1110.   register VIDEO_PTR last;
  1111.   left   += win->xpos;
  1112.   right  += win->xpos;
  1113.   top    += win->ypos;
  1114.   bottom += win->ypos;
  1115.   if (right  > xmax) right = xmax;
  1116.   if (bottom > ymax) bottom = ymax;
  1117.   if(left < 0) left = 0;
  1118.   if(top  < 0) top = 0;
  1119.   if(right  > DISP_MAX_X) right = DISP_MAX_X;
  1120.   if(bottom > DISP_MAX_Y) bottom = DISP_MAX_Y;
  1121.   pixrect* bp = new pixrect;
  1122.   bp->width    = right-left+1;
  1123.   bp->height   = bottom-top+1;
  1124.   bp->bwidth   = right/8 - left/8 + 1;
  1125.   bp->plane[0] = (VIDEO_PTR)malloc(bp->bwidth * bp->height);
  1126.   bp->plane[1] = (VIDEO_PTR)malloc(bp->bwidth * bp->height);
  1127.   bp->plane[2] = (VIDEO_PTR)malloc(bp->bwidth * bp->height);
  1128.   bp->plane[3] = (VIDEO_PTR)malloc(bp->bwidth * bp->height);
  1129.   /* set read mode 0 */
  1130.   port_out(5, GRA_I);
  1131.   port_out(0, GRA_D);
  1132.   /* read planes 0 to 3 */
  1133.   for(int i=0; i<4; i++)
  1134.   { p = bp->plane[i];
  1135.     port_out(4, GRA_I);
  1136.     port_out(i, GRA_D);
  1137.     first = VIDEO + LINE_BYTES*top + left/8;
  1138.     last  = VIDEO + LINE_BYTES*top + right/8;
  1139.     for(y=top; y<=bottom; y++)
  1140.     { for(q=first; q<=last; q++) *p++ = *q;
  1141.       first  += LINE_BYTES;
  1142.       last   += LINE_BYTES;
  1143.      }
  1144.    }
  1145.   return (char*)bp;
  1146. }
  1147. void insert_pixrect(Window w, int left, int top, char* rect)
  1148. { register int y;
  1149.   register VIDEO_PTR p;
  1150.   register VIDEO_PTR q;
  1151.   register VIDEO_PTR pfirst;
  1152.   register VIDEO_PTR first;
  1153.   register VIDEO_PTR last;
  1154.   pixrect* bp = (pixrect*)rect; 
  1155.   DosWindow win = win_stack[w];
  1156.   int xmax = win->xpos + win->width - 1;
  1157.   int ymax = win->ypos + win->height - 1;
  1158.   left   += win->xpos;
  1159.   top    += win->ypos;
  1160.   if(left < 0) left = 0;
  1161.   if(top  < 0) top = 0;
  1162.   int right  = left + bp->width - 1;
  1163.   int bottom = top + bp->height - 1;
  1164.   if (right  > xmax) right = xmax;
  1165.   if (bottom > xmax) bottom = ymax;
  1166.   int save_mode = set_mode(0);
  1167.   int save_col  = set_color(0);
  1168.   // clean area
  1169.   port_out(8, GRA_I);
  1170.   port_out(0xFF, GRA_D);
  1171.   first  = VIDEO + LINE_BYTES*top + left/8;
  1172.   last   = VIDEO + LINE_BYTES*top + right/8;
  1173.   for(y=top; y<=bottom; y++)
  1174.   { for(q=first; q<=last; q++) *q = *q;
  1175.     first  += LINE_BYTES;
  1176.     last   += LINE_BYTES;
  1177.    }
  1178.   // fill in plane data
  1179.   set_mode(2); /* or */
  1180.   for(int i = 0; i < 4; i++)
  1181.   {
  1182.     set_color(1<<i);
  1183.     pfirst = bp->plane[i];
  1184.     first  = VIDEO + LINE_BYTES*top + left/8;
  1185.     last   = VIDEO + LINE_BYTES*top + right/8;
  1186.     port_out(8, GRA_I);
  1187.     for(y=top; y<=bottom; y++)
  1188.     { for(q=first,p=pfirst; q<=last; q++,p++) 
  1189.       { port_out(*p, GRA_D);
  1190.         *q = *q;
  1191.        }
  1192.       pfirst += bp->bwidth;
  1193.       first  += LINE_BYTES;
  1194.       last   += LINE_BYTES;
  1195.      }
  1196.    }
  1197.   
  1198.   set_mode(save_mode);
  1199.   set_color(save_col);
  1200. }
  1201. void delete_pixrect(char* rect)
  1202. { pixrect* bp =(pixrect*)rect;
  1203.   for(int i=0; i<4; i++) free((char*)(bp->plane[i]));
  1204.   delete bp;
  1205.  }
  1206. //------------------------------------------------------------------------------
  1207. // mouse cursor
  1208. //------------------------------------------------------------------------------
  1209. static unsigned char pointer_mask[2][2][14] = { 
  1210. {{0xc0,0xf0,0x7c,0x7f,0x3f,0x3f,0x1f,0x1f,0x0d,0x0c,0x00,0x00,0x00,0x00},
  1211.  {0x00,0x00,0x00,0x00,0xc0,0xc0,0x00,0x80,0xc0,0xe0,0x70,0x38,0x1c,0x0c}},
  1212. {{0x00,0x00,0x00,0x00,0x03,0x03,0x00,0x01,0x03,0x07,0x0e,0x1c,0x38,0x30},
  1213.  {0x03,0x0f,0x3e,0xfe,0xfc,0xfc,0xf8,0xf8,0xb0,0x30,0x00,0x00,0x00,0x00} }
  1214. };
  1215. static void pointer_pixel(int x, int y)
  1216. { if (x < 0 || x > DISP_MAX_X || y < 0 || y > DISP_MAX_Y) return;
  1217.   VIDEO_PTR p = VIDEO + y*LINE_BYTES + (x>>3);
  1218.   port_out(8, GRA_I);
  1219.   port_out((0x80 >> (x & 7)), GRA_D);
  1220.   *p = *p;
  1221. }
  1222. void draw_pointer(int mouse_x, int mouse_y, int shape)
  1223. {
  1224.   register int x1 = mouse_x % 8;
  1225.   register int x2 = 8-x1;
  1226.   register int x = mouse_x/8;
  1227.   VIDEO_PTR start = VIDEO + LINE_BYTES*mouse_y + x;
  1228.   register VIDEO_PTR q;
  1229.   register unsigned char c;
  1230.   set_color(black);
  1231.   if (shape == 1)
  1232.   { pointer_pixel(mouse_x-3,mouse_y);
  1233.     pointer_pixel(mouse_x-2,mouse_y);
  1234.     pointer_pixel(mouse_x-1,mouse_y);
  1235.     pointer_pixel(mouse_x,mouse_y);
  1236.     pointer_pixel(mouse_x+1,mouse_y);
  1237.     pointer_pixel(mouse_x+2,mouse_y);
  1238.     pointer_pixel(mouse_x+3,mouse_y);
  1239.     pointer_pixel(mouse_x,mouse_y-3);
  1240.     pointer_pixel(mouse_x,mouse_y-2);
  1241.     pointer_pixel(mouse_x,mouse_y-1);
  1242.     pointer_pixel(mouse_x,mouse_y+1);
  1243.     pointer_pixel(mouse_x,mouse_y+2);
  1244.     pointer_pixel(mouse_x,mouse_y+3);
  1245.     // circle(mouse_x,mouse_y,3);
  1246.     return;
  1247.    }
  1248.   int a = 0;
  1249.   int b = 14;
  1250.   int d = 1;
  1251.   int k = 0;
  1252.   if (mouse_y + 15 > DISP_MAX_Y) 
  1253.   { a = 13;
  1254.     b = -1;
  1255.     d = -1;
  1256.     start -= 14*LINE_BYTES;
  1257.    }
  1258.   if (x > 77) 
  1259.   { start -= 2;
  1260.     k = 1;
  1261.    }
  1262.   port_out(8, GRA_I);
  1263.   for(int i=a; i!=b; i+=d)
  1264.   { q = start;
  1265.     c = (pointer_mask[k][0][i]>>x1);
  1266.     port_out(c, GRA_D);
  1267.     *q = *q;
  1268.     ++q; 
  1269.     c = ((pointer_mask[k][1][i]>>x1) | (pointer_mask[k][0][i]<<x2));
  1270.     port_out(c, GRA_D);
  1271.     *q = *q;
  1272.     
  1273.     if (x2)
  1274.     { ++q;
  1275.       c = (pointer_mask[k][1][i]<<x2);
  1276.       port_out(c, GRA_D);
  1277.       *q = *q;
  1278.      }
  1279.     start+=LINE_BYTES;
  1280.    }
  1281. }