home *** CD-ROM | disk | FTP | other *** search
- #include <string.h>
- #include <stdfont.h>
-
- #include "pmtext.h"
-
-
- PMTextWindow::PMTextWindow (const char *afontspec,
- int init_width, int init_height)
- : TextWindow (init_width, init_height),
- fontspec (strdup (afontspec))
- {
- // Maxbutton is useless for a fixed-size window application
- disable_maxbutton ();
- // Set the default colors to black on white
- set_fg (0);
- set_bg (15);
- clrscr ();
- // Use current foreground color for the cursor color
- set_cursor_color (-1);
- // Give a reasonable size to the cursor
- set_cursor (0, 2);
- }
-
- PMTextWindow::~PMTextWindow ()
- {
- }
-
- MRESULT PMTextWindow::msg_create ()
- {
- // Initialize the font subsystem
- init_desktop_fontinfo ();
- font = desktop_fontinfo->install_font ("10.System VIO");
-
- // Then measure the height and width of the typical characters
- const FONTMETRICS *fm = desktop_fontinfo->get_fontmetrics (font);
- if (fm == 0)
- {
- HPS hps = WinGetPS (window);
- FONTMETRICS qfm;
- GpiQueryFontMetrics (hps, sizeof qfm, &qfm);
- char_width = qfm.lEmInc;
- char_height = qfm.lMaxBaselineExt;
- char_descender = qfm.lMaxDescender;
- WinReleasePS (hps);
- }
- else
- {
- char_width = desktop_fontinfo->get_font_width (font);
- char_height = desktop_fontinfo->get_font_height (font);
- char_descender = desktop_fontinfo->get_font_descender (font);
- }
-
- // Configure the frame to be the appropriate size for this window
- framectl.set_exact_size (TextWindow::get_screen_width () * char_width,
- TextWindow::get_screen_height () * char_height);
- framectl.attach (frame);
-
- // Then run the default msg create procedure
- MRESULT rc = StdWin::msg_create ();
-
- // Finally, eliminate all the dirty bits from the textwindow struct
- refresh_window ();
-
- return rc;
- }
-
-
- // A routine to convert 16color values into their PM equivalents
- static inline int pccolor_to_pmcolor (int color)
- {
- static int pmcolors[] =
- {
- CLR_BLACK,
- CLR_DARKBLUE,
- CLR_DARKGREEN,
- CLR_DARKCYAN,
- CLR_DARKRED,
- CLR_DARKPINK,
- CLR_BROWN,
- CLR_NEUTRAL,
- CLR_DARKGRAY,
- CLR_BLUE,
- CLR_GREEN,
- CLR_CYAN,
- CLR_RED,
- CLR_PINK,
- CLR_YELLOW,
- CLR_WHITE
- };
- return pmcolors [color & 0x0F];
- }
-
-
- MRESULT PMTextWindow::msg_paint ()
- {
- // Obtain the Presentation Space and determine the bounds of the stuff
- // we need to repaint
- RECTL bounds;
- memset (&bounds, 0, sizeof (bounds));
- HPS hps = WinBeginPaint (window, 0, &bounds);
-
- // Configure the Presentation Space to use our selected font
- desktop_fontinfo->make_fonts_availible (hps);
- desktop_fontinfo->use_font (hps, font);
-
- // Configure so that character drawing rewrites both the foreground
- // and the background with appropriate colors
- CHARBUNDLE charattr;
- charattr.usBackMixMode = FM_OVERPAINT;
- GpiSetAttrs (hps, PRIM_CHAR, CBB_BACK_MIX_MODE, 0, (PBUNDLE) &charattr);
-
- // Cache the screen dimensions into local vars;
- const int screen_height = get_screen_height ();
- const int screen_width = get_screen_width ();
-
- // Calculate the redraw limits in terms of lines and characters
- // rather than pixels. Note the reversal in y values due to the
- // differences between the PM and textwin coordinate systems
- int yTop = screen_height - 1 - (bounds.yTop-1) / char_height;
- int yBottom = screen_height - 1 - bounds.yBottom / char_height;
- int xLeft = bounds.xLeft / char_width;
- int xRight = (bounds.xRight-1) / char_width;
-
- // Limit the redraw limits to sensible values
- #define LIMIT(l, value, h) ((value < l) ? l : (value > h) ? h : value)
- yTop = LIMIT (0, yTop, screen_height - 1);
- yBottom = LIMIT (yTop, yBottom, screen_height - 1);
- xRight = LIMIT (0, xRight, screen_width - 1);
- xLeft = LIMIT (0, xLeft, xRight);
-
- int i;
- POINTL pt;
- int runlength;
- for (i = yTop; i <= yBottom; i++)
- for (int j = xLeft; j <= xRight; j += runlength)
- {
- // Get the color and attribute for the current cell
- const char *text = get_text (j, i);
- const unsigned char *attr = get_attr (j, i);
- const unsigned char a = attr[0];
- // Calculate the maximum run-length of characters with the same attr
- for (runlength = 1; j + runlength <= xRight; runlength++)
- if (attr[runlength] != a)
- break;
- // Configure the drawing color
- charattr.lColor = pccolor_to_pmcolor (a & 0x0F);
- charattr.lBackColor = pccolor_to_pmcolor (a >> 4);
- GpiSetAttrs (hps, PRIM_CHAR, CBB_COLOR | CBB_BACK_COLOR, 0,
- (PBUNDLE) &charattr);
- // Move to the correct position
- pt.y = char_height * (screen_height - i - 1) + char_descender;
- pt.x = char_width * j;
- GpiMove (hps, &pt);
- // Then draw the run length
- GpiCharString (hps, runlength, text);
- // If the cursor is in that last bit of text, draw it too
- if (j <= get_screen_x () && get_screen_x () < j + runlength
- && i == get_screen_y ()
- && visible_cursor)
- {
- // If the cursor is supposed to use a different color
- // than the text, then set the correct color
- if (0 <= cursor_color && cursor_color < 16)
- GpiSetColor (hps, pccolor_to_pmcolor (cursor_color));
- else
- GpiSetColor (hps, pccolor_to_pmcolor (a & 0x0F));
- // Move to the starting position for the cursor block
- pt.x = char_width * get_screen_x ();
- pt.y = (char_height * (screen_height - get_screen_y () - 1)
- + cursor_stop_line);
- GpiMove (hps, &pt);
- // Calculate the opposite corner for the block
- pt.x += char_width;
- pt.y += (cursor_start_line - cursor_stop_line);
- // Then draw it!
- GpiBox (hps, DRO_FILL, &pt, 0, 0);
- }
- }
- WinEndPaint (hps);
- return 0;
- }
-
-
- void PMTextWindow::refresh_window ()
- {
- if (!repaint_needed ())
- return;
- // For each line in the screen, generate the rectangle that needs to
- // be repainted on that line. Then request the repaint of the rectangle.
- const int screen_height = get_screen_height ();
- for (int y = 0; y < screen_height; y++)
- {
- int x1, x2;
- get_dirt (y, &x1, &x2);
- if (x1 != -1)
- {
- RECTL rect;
- rect.xLeft = x1 * char_width;
- rect.xRight = ((x2 + 1) * char_width);
- rect.yTop = ((screen_height - y) * char_height);
- rect.yBottom = (screen_height - y - 1) * char_height;
- WinInvalidateRect (window, &rect, 0);
- }
- }
- }
-
- int PMTextWindow::scroll_region_draw (int scroll_distance,
- int x1, int y1, int x2, int y2)
- {
- // Convert the coordinates into a rectangle
- RECTL rect;
- rect.xLeft = x1 * char_width;
- rect.xRight = ((x2 + 1) * char_width);
- rect.yTop = ((get_screen_height () - 1 - y1) * char_height);
- rect.yBottom = (get_screen_height () - 1 - y2 - 1) * char_height;
-
- // Bad Things happen if we don't invalidate the exposed region.
- // I don't understand why though.
- WinScrollWindow (window, 0, scroll_distance * char_height,
- &rect, 0, 0, 0, 0/*SW_INVALIDATERGN*/);
- return 1;
-
- }
-
- void PMTextWindow::hide_cursor ()
- {
- visible_cursor = 0;
- }
-
- void PMTextWindow::set_cursor (int start_line, int stop_line)
- {
- visible_cursor = 1;
- cursor_start_line = start_line;
- cursor_stop_line = stop_line;
- }
-
- void PMTextWindow::set_cursor_color (int color)
- {
- cursor_color = color;
- }
-
- int PMTextWindow::get_cursor_color () const
- {
- return cursor_color;
- }
-