home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / spmio10.zip / gcc2 / pmio / pmtext.cc < prev    next >
C/C++ Source or Header  |  1994-06-18  |  7KB  |  246 lines

  1. #include <string.h>
  2. #include <stdfont.h>
  3.  
  4. #include "pmtext.h"
  5.  
  6.  
  7. PMTextWindow::PMTextWindow (const char *afontspec,
  8.                 int init_width, int init_height)
  9. : TextWindow (init_width, init_height),
  10.   fontspec (strdup (afontspec))
  11. {
  12.   // Maxbutton is useless for a fixed-size window application
  13.   disable_maxbutton ();
  14.   // Set the default colors to black on white
  15.   set_fg (0);
  16.   set_bg (15);
  17.   clrscr ();
  18.   // Use current foreground color for the cursor color
  19.   set_cursor_color (-1);
  20.   // Give a reasonable size to the cursor
  21.   set_cursor (0, 2);
  22. }
  23.  
  24. PMTextWindow::~PMTextWindow ()
  25. {
  26. }
  27.  
  28. MRESULT PMTextWindow::msg_create ()
  29. {
  30.   // Initialize the font subsystem
  31.   init_desktop_fontinfo ();
  32.   font = desktop_fontinfo->install_font ("10.System VIO");
  33.  
  34.   // Then measure the height and width of the typical characters
  35.   const FONTMETRICS *fm = desktop_fontinfo->get_fontmetrics (font);
  36.   if (fm == 0)
  37.     {
  38.       HPS hps = WinGetPS (window);
  39.       FONTMETRICS qfm;
  40.       GpiQueryFontMetrics (hps, sizeof qfm, &qfm);
  41.       char_width = qfm.lEmInc;
  42.       char_height = qfm.lMaxBaselineExt;
  43.       char_descender = qfm.lMaxDescender;
  44.       WinReleasePS (hps);
  45.     }
  46.   else
  47.     {
  48.       char_width = desktop_fontinfo->get_font_width (font);
  49.       char_height = desktop_fontinfo->get_font_height (font);
  50.       char_descender = desktop_fontinfo->get_font_descender (font);
  51.     }
  52.  
  53.   // Configure the frame to be the appropriate size for this window
  54.   framectl.set_exact_size (TextWindow::get_screen_width () * char_width,
  55.                TextWindow::get_screen_height () * char_height);
  56.   framectl.attach (frame);
  57.  
  58.   // Then run the default msg create procedure
  59.   MRESULT rc = StdWin::msg_create ();
  60.  
  61.   // Finally, eliminate all the dirty bits from the textwindow struct
  62.   refresh_window ();
  63.  
  64.   return rc;
  65. }
  66.  
  67.  
  68. // A routine to convert 16color values into their PM equivalents
  69. static inline int pccolor_to_pmcolor (int color)
  70. {
  71.   static int pmcolors[] =
  72.     {
  73.       CLR_BLACK,
  74.       CLR_DARKBLUE,
  75.       CLR_DARKGREEN,
  76.       CLR_DARKCYAN,
  77.       CLR_DARKRED,
  78.       CLR_DARKPINK,
  79.       CLR_BROWN,
  80.       CLR_NEUTRAL,
  81.       CLR_DARKGRAY,
  82.       CLR_BLUE,
  83.       CLR_GREEN,
  84.       CLR_CYAN,
  85.       CLR_RED,
  86.       CLR_PINK,
  87.       CLR_YELLOW,
  88.       CLR_WHITE
  89.       };
  90.   return pmcolors [color & 0x0F];
  91. }
  92.  
  93.  
  94. MRESULT PMTextWindow::msg_paint ()
  95. {
  96.   // Obtain the Presentation Space and determine the bounds of the stuff
  97.   // we need to repaint
  98.   RECTL bounds;
  99.   memset (&bounds, 0, sizeof (bounds));
  100.   HPS hps = WinBeginPaint (window, 0, &bounds);
  101.  
  102.   // Configure the Presentation Space to use our selected font
  103.   desktop_fontinfo->make_fonts_availible (hps);
  104.   desktop_fontinfo->use_font (hps, font);
  105.   
  106.   // Configure so that character drawing rewrites both the foreground
  107.   // and the background with appropriate colors
  108.   CHARBUNDLE charattr;
  109.   charattr.usBackMixMode = FM_OVERPAINT;
  110.   GpiSetAttrs (hps, PRIM_CHAR, CBB_BACK_MIX_MODE, 0, (PBUNDLE) &charattr);
  111.  
  112.   // Cache the screen dimensions into local vars;
  113.   const int screen_height = get_screen_height ();
  114.   const int screen_width = get_screen_width ();
  115.  
  116.   // Calculate the redraw limits in terms of lines and characters
  117.   // rather than pixels.  Note the reversal in y values due to the
  118.   // differences between the PM and textwin coordinate systems
  119.   int yTop = screen_height - 1 - (bounds.yTop-1) / char_height;
  120.   int yBottom = screen_height - 1 - bounds.yBottom / char_height;
  121.   int xLeft = bounds.xLeft / char_width;
  122.   int xRight = (bounds.xRight-1) / char_width;
  123.   
  124.   // Limit the redraw limits to sensible values
  125. #define LIMIT(l, value, h) ((value < l) ? l : (value > h) ? h : value)
  126.   yTop = LIMIT (0, yTop, screen_height - 1);
  127.   yBottom = LIMIT (yTop, yBottom, screen_height - 1);
  128.   xRight = LIMIT (0, xRight, screen_width - 1);
  129.   xLeft = LIMIT (0, xLeft, xRight);
  130.  
  131.   int i;
  132.   POINTL pt;
  133.   int runlength;
  134.   for (i = yTop; i <= yBottom; i++)
  135.     for (int j = xLeft; j <= xRight; j += runlength)
  136.       {
  137.     // Get the color and attribute for the current cell
  138.     const char *text = get_text (j, i);
  139.     const unsigned char *attr = get_attr (j, i);
  140.     const unsigned char a = attr[0];
  141.     // Calculate the maximum run-length of characters with the same attr
  142.     for (runlength = 1; j + runlength <= xRight; runlength++)
  143.       if (attr[runlength] != a)
  144.         break;
  145.     // Configure the drawing color
  146.     charattr.lColor = pccolor_to_pmcolor (a & 0x0F);
  147.     charattr.lBackColor = pccolor_to_pmcolor (a >> 4);
  148.     GpiSetAttrs (hps, PRIM_CHAR, CBB_COLOR | CBB_BACK_COLOR, 0, 
  149.              (PBUNDLE) &charattr);
  150.     // Move to the correct position
  151.     pt.y = char_height * (screen_height - i - 1) + char_descender;
  152.     pt.x = char_width * j;
  153.     GpiMove (hps, &pt);
  154.     // Then draw the run length
  155.     GpiCharString (hps, runlength, text);
  156.     // If the cursor is in that last bit of text, draw it too
  157.     if (j <= get_screen_x () && get_screen_x () < j + runlength
  158.         && i == get_screen_y ()
  159.         && visible_cursor)
  160.       {
  161.         // If the cursor is supposed to use a different color
  162.         // than the text, then set the correct color
  163.         if (0 <= cursor_color && cursor_color < 16)
  164.           GpiSetColor (hps, pccolor_to_pmcolor (cursor_color));
  165.         else
  166.           GpiSetColor (hps, pccolor_to_pmcolor (a & 0x0F));
  167.         // Move to the starting position for the cursor block
  168.         pt.x = char_width * get_screen_x ();
  169.         pt.y = (char_height * (screen_height - get_screen_y () - 1)
  170.             + cursor_stop_line);
  171.         GpiMove (hps, &pt);
  172.         // Calculate the opposite corner for the block
  173.         pt.x += char_width;
  174.         pt.y += (cursor_start_line - cursor_stop_line);
  175.         // Then draw it!
  176.         GpiBox (hps, DRO_FILL, &pt, 0, 0);
  177.       }
  178.       }
  179.   WinEndPaint (hps);
  180.   return 0;
  181. }
  182.  
  183.  
  184. void PMTextWindow::refresh_window ()
  185. {
  186.   if (!repaint_needed ())
  187.     return;
  188.   // For each line in the screen, generate the rectangle that needs to
  189.   // be repainted on that line.  Then request the repaint of the rectangle.
  190.   const int screen_height = get_screen_height ();
  191.   for (int y = 0; y < screen_height; y++)
  192.     {
  193.       int x1, x2;
  194.       get_dirt (y, &x1, &x2);
  195.       if (x1 != -1)
  196.     {
  197.       RECTL rect;
  198.       rect.xLeft = x1 * char_width;
  199.       rect.xRight = ((x2 + 1) * char_width);
  200.       rect.yTop = ((screen_height - y) * char_height);
  201.       rect.yBottom = (screen_height - y - 1) * char_height;
  202.       WinInvalidateRect (window, &rect, 0);
  203.     }
  204.     }
  205. }
  206.  
  207. int PMTextWindow::scroll_region_draw (int scroll_distance,
  208.                       int x1, int y1, int x2, int y2)
  209. {
  210.   // Convert the coordinates into a rectangle
  211.   RECTL rect;
  212.   rect.xLeft = x1 * char_width;
  213.   rect.xRight = ((x2 + 1) * char_width);
  214.   rect.yTop = ((get_screen_height () - 1 - y1) * char_height);
  215.   rect.yBottom = (get_screen_height () - 1 - y2 - 1) * char_height;
  216.  
  217.   // Bad Things happen if we don't invalidate the exposed region.
  218.   // I don't understand why though.
  219.   WinScrollWindow (window, 0, scroll_distance * char_height,
  220.            &rect, 0, 0, 0, 0/*SW_INVALIDATERGN*/);
  221.   return 1;
  222.  
  223. }
  224.  
  225. void PMTextWindow::hide_cursor ()
  226. {
  227.   visible_cursor = 0;
  228. }
  229.  
  230. void PMTextWindow::set_cursor (int start_line, int stop_line)
  231. {
  232.   visible_cursor = 1;
  233.   cursor_start_line = start_line;
  234.   cursor_stop_line = stop_line;
  235. }
  236.  
  237. void PMTextWindow::set_cursor_color (int color)
  238. {
  239.   cursor_color = color;
  240. }
  241.  
  242. int PMTextWindow::get_cursor_color () const
  243. {
  244.   return cursor_color;
  245. }
  246.