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