home *** CD-ROM | disk | FTP | other *** search
- // Zinc Interface Library - TXTDSP.CPP
- // COPYRIGHT (C) 1990, 1991. All Rights Reserved.
- // Zinc Software Incorporated. Pleasant Grove, Utah USA
-
- #include "ui_dsp.hpp"
- #include <dos.h>
- #include <mem.h>
- #include <conio.h>
- #include <string.h>
-
- int UI_DOS_TEXT_DISPLAY::forceMono = FALSE;
- UCHAR UI_DOS_TEXT_DISPLAY::displayCode = DC_NO_DISPLAY;
- UCHAR UI_DOS_TEXT_DISPLAY::oldVideoMode;
-
- // VideoInt executes BIOS interrupt 10H and insures BP is preserved.
- void VideoInt(void)
- {
- asm push bp // Save BP
- asm int 10H // because INT 10H may clobber it
- asm pop bp // due to bug in older BIOS versions
- }
-
- static void EgaCursor(void)
- {
- _DX = *((USHORT far *)0x463L);
- asm mov al, 14H
- asm out dx, al
- asm inc dx
- asm mov al, 7
- asm out dx, al
- }
-
- // TopViewUpdate - Update the screen from the internal TopView buffer.
- static void TopViewUpdate(void)
- {
- asm push bp
- asm push di
- asm push si
- asm mov ah, 0FFH
- asm int 10H
- asm pop si
- asm pop di
- asm pop bp
- }
-
- #pragma argsused
- UI_DOS_TEXT_DISPLAY::UI_DOS_TEXT_DISPLAY(int mode) :
- UI_DISPLAY(TRUE, 1, 1)
- {
- UCHAR equipmentFlags;
-
- // Save the current video state.
- equipmentFlags = *((UCHAR far *)0x410L);
- _AX = 0x1A00;
- VideoInt();
- if (_AL != 0x1A) // Display Combination Code call not supported.
- {
- UCHAR egaCode;
- _AH = 0x12;
- _BL = 0x10;
- VideoInt();
- egaCode = (_BL == 0x10) ? 0 : DC_EGA_COLOR + _BH;
- if ((equipmentFlags & 0x30) == 0x30) // Primary mono
- {
- displayCode = DC_MONOCHROME;
- if (egaCode == DC_EGA_MONO)
- displayCode = DC_EGA_MONO;
- }
- else
- {
- displayCode = egaCode ? egaCode : DC_CGA;
- }
- }
- else
- {
- displayCode = _BL;
- }
- // Save the current video state.
- _AH = 0x0F;
- VideoInt();
- _DL = _AL;
- oldVideoMode = _DL;
- // oldVideoMode = _AL; // Borland Bug: Doesn't work in large model
- USHORT newSegment;
- USHORT newOffset;
-
- if ((mode == TDM_43x80 && displayCode < DC_EGA_COLOR) ||
- (mode == TDM_25x40 && displayCode == DC_MONOCHROME))
- return;
- retraceWait = (displayCode == DC_CGA) ? TRUE : FALSE;
-
- _BH = 0;
- _AH = 3;
- VideoInt();
- originalCursorValue = _CX; // Save original cursor value.
- originalCursorEmulationBit = *((UCHAR far *)0x487L) & 1;
-
- // Set the new video mode.
- if (((equipmentFlags & 0x30) == 0x10) || mode == TDM_25x40)
- videoMode = forceMono ? 0x00 : 0x01; // 40 column mode.
- else if (displayCode == DC_MONOCHROME)
- videoMode = 7;
- else
- videoMode = forceMono ? 0x02 : 0x03;
- _AX = (USHORT)videoMode;
- VideoInt();
- delay(60); // For benefit of suspected VEGA VGA BIOS bug.
-
- // Check the new video state.
- _AH = 0x0F;
- VideoInt();
- if (_AL == 7)
- {
- segment = 0xB000;
- isMono = TRUE;
- onCursorValue = 0x0B0C;
- offCursorValue = 0x2000;
- }
- else
- {
- segment = 0xB800;
- isMono = FALSE;
- onCursorValue = 0x0607;
- offCursorValue = 0x2000;
- }
- _AH = 1;
- VideoInt(); // Turn off the cursor.
-
- // Put in check for Hercules In-Color Card later.
- desqview = FALSE;
- topview = FALSE;
- offset = 0;
- _DX = segment;
- _DI = offset;
- _ES = _DX;
- _AH = 0xFE;
- VideoInt();
- newSegment = _ES;
- newOffset = _DI;
- if (newSegment != segment || newOffset != offset)
- {
- segment = newSegment;
- offset = newOffset;
- retraceWait = FALSE;
- _CX = 'ED';
- _DX = 'QS';
- _AX = 0x2B01;
- geninterrupt(0x21);
- if (_AL == 0xFF)
- topview = TRUE;
- else
- desqview = TRUE;
- }
- if (mode == TDM_43x80 && displayCode >= DC_EGA_COLOR)
- {
- if (displayCode == DC_EGA_COLOR || displayCode == DC_EGA_MONO)
- lines = 43;
- else
- lines = 50;
- _BL = 0;
- _AX = 0x1112; // Load ROM BIOS 8x8 characters
- VideoInt();
- if (displayCode <= DC_EGA_MONO)
- {
- *((UCHAR far *)0x487L) |= 1; // Inhibit cursor emulation.
- _CX = 0x0607; // (start on 6, off on 7)
- _AH = 0x01;
- VideoInt();
- EgaCursor();
- }
- _BL = 0x20;
- _AH = 0x12;
- VideoInt(); // Set alternate print screen routine.
- }
- else
- lines = 25;
- columns = *((USHORT far *)0x44AL);
- if (*((UCHAR far *)0x484L))
- lines = *((UCHAR far *)0x484L) + 1;
- SetBlink(FALSE); // Turn off blink by default.
-
- // Check for special text mode monitors.
- struct text_info textInfo;
- gettextinfo(&textInfo);
- if (textInfo.currmode == BW80 || textInfo.currmode == BW40)
- isMono = TRUE;
-
- // Fill the screen according to the specified palette.
- for (int i = 0; i < lines; i++)
- FillLine(0, i, columns, _backgroundPalette);
-
- // Define the screen display region.
- Add(0, new UI_REGION_ELEMENT(ID_SCREEN, 0, 0, columns - 1, lines - 1));
- installed = TRUE;
- }
-
- UI_DOS_TEXT_DISPLAY::~UI_DOS_TEXT_DISPLAY(void)
- {
- _AX = (USHORT)oldVideoMode;
- VideoInt();
- if (displayCode == DC_EGA_MONO || displayCode == DC_EGA_COLOR)
- *((UCHAR far *)0x487) = (*((UCHAR far *)0x487L) & ~1) | originalCursorEmulationBit;
- _CX = originalCursorValue;
- _AH = 1;
- VideoInt();
- }
-
- #pragma argsused
- void UI_DOS_TEXT_DISPLAY::Bitmap(SCREENID screenID, int column, int line,
- int bitmapWidth, int bitmapHeight, const UCHAR *bitmapArray,
- const UI_PALETTE *palette, const UI_REGION *clipRegion)
- {
- }
-
- #pragma argsused
- void UI_DOS_TEXT_DISPLAY::Ellipse(SCREENID screenID, int column, int line,
- int startAngle, int endAngle, int xRadius, int yRadius,
- const UI_PALETTE *palette, int fill, int xor, const UI_REGION *clipRegion)
- {
- }
-
- #pragma argsused
- void UI_DOS_TEXT_DISPLAY::Line(SCREENID screenID, int column1, int line1,
- int column2, int line2, const UI_PALETTE *palette, int width, int xor,
- const UI_REGION *clipRegion)
- {
- if (xor)
- {
- Rectangle(screenID, column1, line1, column2, line2, palette, 0,
- FALSE, TRUE, clipRegion);
- return;
- }
-
- // Ensure a left-top to right-bottom line.
- if (column2 < column1)
- {
- int column = column1;
- column1 = column2;
- column2 = column;
- }
- if (line2 < line1)
- {
- int line = line1;
- line1 = line2;
- line2 = line;
- }
-
- // Set up the line region.
- UI_REGION region;
- region.left = column1;
- region.top = line1;
- region.right = column2;
- region.bottom = line2;
- if (clipRegion)
- {
- region.left = Max(region.left, clipRegion->left);
- region.top = Max(region.top, clipRegion->top);
- region.right = Min(region.right, clipRegion->right);
- region.bottom = Min(region.bottom, clipRegion->bottom);
- }
-
- // Hide the screen devices.
- if (eventManager)
- eventManager->DevicesHide(region);
-
- // Compute the display character.
- UI_PALETTE t_palette = *palette;
- if (column1 == column2) // Vertical line
- t_palette.fillCharacter = (width == 1) ? 0xB3 : 0xBA;
- else if (line1 == line2) // Horizontal line
- t_palette.fillCharacter = (width == 1) ? 0xC4 : 0xCD;
- else
- t_palette.fillCharacter = 0;
-
- // Draw a line on the display.
- if (t_palette.fillCharacter)
- Fill(screenID, region, &t_palette);
- if (topview)
- TopViewUpdate();
-
- // Show the screen devices.
- if (eventManager)
- eventManager->DevicesShow(region);
- }
-
- #pragma argsused
- void UI_DOS_TEXT_DISPLAY::Polygon(SCREENID screenID, int numPoints,
- const int *polygonPoints, const UI_PALETTE *palette, int fill, int xor,
- const UI_REGION *clipRegion)
- {
- }
-
- #pragma argsused
- void UI_DOS_TEXT_DISPLAY::Rectangle(SCREENID screenID, int left, int top, int right,
- int bottom, const UI_PALETTE *palette, int width, int fill, int xor,
- const UI_REGION *clipRegion)
- {
- UI_REGION region;
-
- region.left = left;
- region.top = top;
- region.right = right;
- region.bottom = bottom;
- if (clipRegion)
- {
- region.left = Max(region.left, clipRegion->left);
- region.top = Max(region.top, clipRegion->top);
- region.right = Min(region.right, clipRegion->right);
- region.bottom = Min(region.bottom, clipRegion->bottom);
- }
- if (xor)
- {
- if (fill)
- FillXOR(region);
- else
- RectangleXOR(region);
- }
- else
- {
- #if 0
- RectangleOnly(screenID, region, palette, width);
- if (fill) {
- region.left++;
- region.right--;
- region.top++;
- region.bottom--;
- Fill(screenID, region, palette);
- }
- #else
- if (fill)
- Fill(screenID, region, palette);
- else
- RectangleOnly(screenID, region, palette, width);
- #endif
- }
- }
-
- void UI_DOS_TEXT_DISPLAY::RectangleXOR(const UI_REGION ®ion)
- {
- // See if it is a 1 cell rectangle.
- if (region.left == region.right && region.top == region.bottom)
- {
- UI_DOS_TEXT_DISPLAY::FillXOR(region);
- return;
- }
-
- // Hide the screen devices.
- if (eventManager)
- eventManager->DevicesHide(region);
-
- // Draw an XOR rectangle on the display.
- if (region.top >= 0 && region.top < lines)
- {
- for (int column = Max(region.left, 0); column <= Min(region.right, columns - 1); column++)
- XorAttribute(column, region.top);
- }
- if (region.top < region.bottom)
- {
- for (int row = Max(region.top + 1, 0); row < Min(region.bottom, lines); row++)
- {
- if (region.left >= 0)
- XorAttribute(region.left, row);
- if ((region.left != region.right || region.left < 0) && region.right < columns)
- XorAttribute(region.right, row);
- }
- if (region.bottom < lines)
- {
- for (int column = Max(region.left, 0); column <= Min(region.right, columns - 1); column++)
- XorAttribute(column, region.bottom);
- }
- }
- if (topview)
- TopViewUpdate();
-
- // Show the screen devices.
- if (eventManager)
- eventManager->DevicesShow(region);
- }
-
- #pragma argsused
- void UI_DOS_TEXT_DISPLAY::RectangleXORDiff(const UI_REGION &oldRegion,
- const UI_REGION &newRegion)
- {
- static char *cell = 0;
-
- // Allocate space for the XOR region.
- if (&oldRegion == &newRegion)
- {
- if (cell)
- delete cell;
- cell = 0;
- return;
- }
- else if (!cell)
- cell = new char[lines * columns];
-
- // Set up the hide region.
- if (oldRegion.left == newRegion.left && oldRegion.top == newRegion.top &&
- oldRegion.right == newRegion.right && oldRegion.bottom == newRegion.bottom)
- return;
- UI_REGION region;
- region.left = Min(oldRegion.left, newRegion.left);
- region.top = Min(oldRegion.top, newRegion.top);
- region.right = Max(oldRegion.right, newRegion.right);
- region.bottom = Max(oldRegion.bottom, newRegion.bottom);
-
- // Hide the screen devices.
- if (eventManager)
- eventManager->DevicesHide(region);
-
- // Clear the array.
- char *tCell;
- int i, j, iMin, iMax, jMin, jMax;
- memset(cell, 0, lines * columns);
-
- // Find the difference of the two regions.
- iMin = Max(oldRegion.top, 0);
- iMax = Min(oldRegion.bottom, lines - 1);
- jMin = Max(oldRegion.left + 1, 0);
- jMax = Min(oldRegion.right, columns);
- for (i = iMin; i <= iMax; i++)
- {
- if (oldRegion.left >= 0)
- cell[i * columns + oldRegion.left] ^= 1;
- if (oldRegion.right < columns)
- cell[i * columns + oldRegion.right] ^= 1;
- if (i == oldRegion.top || i == oldRegion.bottom)
- for (j = jMin, tCell = &cell[i * columns + jMin]; j < jMax; j++, tCell++)
- *tCell ^= 1;
- }
- iMin = Max(newRegion.top, 0);
- iMax = Min(newRegion.bottom, lines - 1);
- jMin = Max(newRegion.left + 1, 0);
- jMax = Min(newRegion.right, columns);
- for (i = iMin; i <= iMax; i++)
- {
- if (newRegion.left >= 0)
- cell[i * columns + newRegion.left] ^= 1;
- if (newRegion.right < columns)
- cell[i * columns + newRegion.right] ^= 1;
- if (i == newRegion.top || i == newRegion.bottom)
- for (j = jMin, tCell = &cell[i * columns + jMin]; j < jMax; j++, tCell++)
- *tCell ^= 1;
- }
-
- // XOR the cell differences.
- iMin = Max(0, Min(oldRegion.top, newRegion.top));
- iMax = Min(lines - 1, Max(oldRegion.bottom, newRegion.bottom));
- jMin = Max(0, Min(oldRegion.left, newRegion.left));
- jMax = Min(columns - 1, Max(oldRegion.right, newRegion.right));
- for (i = iMin; i <= iMax; i++)
- for (j = jMin, tCell = &cell[i * columns + jMin]; j <= jMax; j++, tCell++)
- if (*tCell)
- XorAttribute(j, i);
- if (topview)
- TopViewUpdate();
-
- // Show the screen devices.
- if (eventManager)
- eventManager->DevicesShow(region);
- }
-
- #pragma argsused
- void UI_DOS_TEXT_DISPLAY::RegionConvert(UI_REGION ®ion, USHORT *oldFlags, USHORT newFlags)
- {
- // Check for a convertable region.
- if (!FlagSet(*oldFlags, newFlags))
- return;
-
- // These variables handle Text<-->Graphics coordinate problems.
- region.left /= 8;
- region.top /= 14;
- region.right /= 8;
- region.bottom /= 14;
-
- *oldFlags &= ~newFlags;
- }
-
- #pragma argsused
- void UI_DOS_TEXT_DISPLAY::RegionMove(const UI_REGION &oldRegion, int newColumn, int newLine,
- SCREENID oldScreenID, SCREENID newScreenID)
- {
- unsigned width = oldRegion.right - oldRegion.left + 1;
- unsigned height = oldRegion.bottom - oldRegion.top + 1;
- char *buffer = new char[width * height * 2];
- gettext(oldRegion.left + 1, oldRegion.top + 1, oldRegion.right + 1,
- oldRegion.bottom + 1, buffer);
- puttext(newColumn, newLine, newColumn + width - 1, newLine + height - 1,
- buffer);
- delete buffer;
- }
-
- #pragma argsused
- void UI_DOS_TEXT_DISPLAY::Text(SCREENID screenID, int left, int top,
- const char *text, const UI_PALETTE *palette, int length,
- int fill, int xor, const UI_REGION *clipRegion)
- {
- int start;
- UI_REGION region;
- UI_REGION t_region;
- UI_REGION dRegion;
-
- if (xor)
- {
- TextXOR(left, top, length);
- // Rectangle(screenID, left, top, left + length - 1, top,
- // palette, 1, TRUE, TRUE);
- return;
- }
- // Draw the text on the display.
- region.left = left;
- region.top = top;
- region.right = left + (length == -1 ? strlen(text) : length) - 1;
- region.bottom = top;
- if (clipRegion)
- {
- region.left = Max(region.left, clipRegion->left);
- region.top = Max(region.top, clipRegion->top);
- region.right = Min(region.right, clipRegion->right);
- region.bottom = Min(region.bottom, clipRegion->bottom);
- }
- dRegion = region;
-
- // Hide the screen devices.
- if (eventManager)
- eventManager->DevicesHide(dRegion);
-
- // Display the text.
- for (UI_REGION_ELEMENT *d_region = First(); d_region; d_region = d_region->Next())
- if (d_region->screenID == screenID &&
- d_region->Overlap(region, t_region) &&
- region.top >= t_region.top)
- {
- int right = (region.right > t_region.right) ? t_region.right : region.right;
- if (region.left < t_region.left)
- {
- start = t_region.left - region.left;
- DrawText(palette, t_region.left, region.top, &text[start],
- right + 1 - t_region.left);
- }
- else
- DrawText(palette, region.left, region.top, text,
- right + 1 - region.left);
- }
- if (topview)
- TopViewUpdate();
-
- // Show the screen devices.
- if (eventManager)
- eventManager->DevicesShow(dRegion);
- }
-
- #pragma argsused
- int UI_DOS_TEXT_DISPLAY::TextHeight(const char *string, SCREENID screenID)
- {
- return (1);
- }
-
- #pragma argsused
- int UI_DOS_TEXT_DISPLAY::TextWidth(const char *string, SCREENID screenID)
- {
- return (strlen(string));
- }
-
- void UI_DOS_TEXT_DISPLAY::DrawText(const UI_PALETTE *palette, int column,
- int line, const char *text, int length)
- {
- USHORT t_segment = segment;
- USHORT t_offset = offset + line * columns * 2 + column * 2;
-
- _DL = retraceWait;
- _DH = isMono ? palette->monoAttribute : palette->colorAttribute;
- _CX = length;
- _DI = t_offset;
- _ES = t_segment;
- #if sizeof(text) == 4
- asm push ds
- asm mov si, WORD PTR text
- asm mov ds, WORD PTR text + 2
- #else
- asm mov si, text
- #endif
- asm mov bh, dh // Save attribute in BH
- asm or dl, dl
- asm jz fast_draw
-
- asm mov dx, 3DAH // Get address of Motorola 6845 to DX
-
- next_char:
- asm lodsb
- asm mov bl, al
- wait_lo:
- asm in al, dx
- asm rcr al, 1
- asm jc wait_lo
-
- asm cli
-
- wait_hi:
- asm in al, dx
- asm rcr al, 1
- asm jnc wait_hi
-
- asm mov ax, bx
- asm stosw
- asm sti
- asm loop next_char
-
- asm jmp short draw_done
-
- fast_draw:
- asm mov ah, bh
-
- fast_loop:
- asm lodsb
- asm stosw
- asm loop fast_loop
-
- draw_done:;
- #if sizeof(text) == 4
- asm pop ds
- #endif
- }
-
- void UI_DOS_TEXT_DISPLAY::SetBlink(int enableBlink)
- {
- if (displayCode >= DC_EGA_COLOR)
- {
- _BL = enableBlink ? 1 : 0;
- _AX = 0x1003;
- VideoInt();
- }
- else
- {
- UCHAR newSetting = *((UCHAR far *)0x465L);
- newSetting = (enableBlink) ? newSetting | 0x20 : newSetting & ~0x20;
- outportb(*((USHORT far *)0x463L) + 4, newSetting);
- *((UCHAR far *)0x465L) = newSetting; // Update BIOS data area
- }
- blinkState = enableBlink;
- }
-
- void UI_DOS_TEXT_DISPLAY::Fill(SCREENID screenID, const UI_REGION ®ion,
- const UI_PALETTE *palette)
- {
- UI_REGION t_region;
-
- // Hide the screen devices.
- if (eventManager)
- eventManager->DevicesHide(region);
-
- // Fill a zone on the display.
- for (UI_REGION_ELEMENT *d_region = First(); d_region; d_region = d_region->Next())
- if (d_region->screenID == screenID &&
- d_region->Overlap(region, t_region))
- {
- for (int i = t_region.top; i <= t_region.bottom; i++)
- FillLine(t_region.left, i, t_region.right + 1 - t_region.left, palette);
- }
- if (topview)
- TopViewUpdate();
-
- // Show the screen devices.
- if (eventManager)
- eventManager->DevicesShow(region);
- }
-
- void UI_DOS_TEXT_DISPLAY::FillXOR(const UI_REGION ®ion)
- {
- int i, j;
- for (i = region.left; i <= region.right; i++)
- for (j = region.top; j <= region.bottom; j++)
- XorAttribute(i, j);
- if (topview)
- TopViewUpdate();
- }
-
- void UI_DOS_TEXT_DISPLAY::FillLine(int column, int line, int noOfCharacters,
- const UI_PALETTE *palette)
- {
- USHORT t_segment = segment;
- USHORT t_offset = offset + line * columns * 2 + column * 2;
-
- _DL = retraceWait;
- _CH = isMono ? palette->monoAttribute : palette->colorAttribute;
- _CL = palette->fillCharacter;
- _BX = _CX; // Save to BX.
- _CX = noOfCharacters;
- _DI = t_offset;
- _ES = t_segment;
- asm or dl, dl
- asm jz fast_fill
-
- asm mov dx, 3DAH // Get address of Motorola 6845 to DX
-
- wait_lo:
- asm in al, dx
- asm rcr al, 1
- asm jc wait_lo
-
- asm cli
-
- wait_hi:
- asm in al, dx
- asm rcr al, 1
- asm jnc wait_hi
-
- asm mov ax, bx
- asm stosw
- asm sti
- asm loop wait_lo
-
- asm jmp short fill_done
-
- fast_fill:
- asm mov ax, bx
- asm rep stosw
- fill_done:;
- }
-
- void UI_DOS_TEXT_DISPLAY::RectangleOnly(SCREENID screenID, const UI_REGION ®ion,
- const UI_PALETTE *palette, int width)
- {
- static char cornerUL[] = { 0xDA, 0, 0xC9, 0 };
- static char cornerUR[] = { 0xBF, 0, 0xBB, 0 };
- static char cornerLL[] = { 0xC0, 0, 0xC8, 0 };
- static char cornerLR[] = { 0xD9, 0, 0xBC, 0 };
-
- // Hide the screen devices.
- if (eventManager)
- eventManager->DevicesHide(region);
-
- // Draw a box on the display.
- if (region.right > region.left && region.bottom > region.top)
- {
- if (region.right > region.left + 1)
- {
- // NOTE: The next two lines of code are a kludge to get around
- // the problem that Line() has with drawing a line which consists of
- // a single character. It doesn't know whether to use the
- // horizontal or vertical character. Currently it defaults to
- // vertical. To get around this problem, this code makes it draw one
- // extra character to force the line to be horizontal. The extra
- // character is overwritten anyway when the corners are drawn.
- int rightEdge = region.right - 1;
- if (rightEdge == region.left + 1)
- rightEdge++;
- Line(screenID, region.left + 1, region.top, rightEdge, region.top, palette, width);
- Line(screenID, region.left + 1, region.bottom, rightEdge, region.bottom, palette, width);
- }
- if (region.bottom > region.top + 1)
- {
- Line(screenID, region.left, region.top + 1, region.left, region.bottom - 1, palette, width);
- Line(screenID, region.right, region.top + 1, region.right, region.bottom - 1, palette, width);
- }
- width = 2 * (width - 1);
- Text(screenID, region.left, region.top, &cornerUL[width], palette, -1, FALSE);
- Text(screenID, region.right, region.top, &cornerUR[width], palette, -1, FALSE);
- Text(screenID, region.left, region.bottom, &cornerLL[width], palette, -1, FALSE);
- Text(screenID, region.right, region.bottom, &cornerLR[width], palette, -1, FALSE);
- }
- if (topview)
- TopViewUpdate();
-
- // Show the screen devices.
- if (eventManager)
- eventManager->DevicesShow(region);
- }
-
- void UI_DOS_TEXT_DISPLAY::TextXOR(int left, int top, int length)
- {
- // Set up the text region.
- UI_REGION region;
- region.left = left;
- region.top = top;
- region.right = left + length - 1;
- region.bottom = top;
-
- // Hide the screen devices.
- if (eventManager)
- eventManager->DevicesHide(region);
-
- // Draw an XOR rectangle on the display.
- if (region.top >= 0 && region.top < lines)
- {
- for (int column = Max(region.left, 0); column <= Min(region.right, columns - 1); column++)
- XorAttribute(column, region.top, TRUE);
- }
- if (topview)
- TopViewUpdate();
-
- // Show the screen devices.
- if (eventManager)
- eventManager->DevicesShow(region);
- }
-
- void UI_DOS_TEXT_DISPLAY::XorAttribute(int column, int line, int swapNibbles)
- {
- USHORT t_segment = segment;
- USHORT t_offset = offset + line * columns * 2 + column * 2;
-
- asm push ds
- _DH = swapNibbles;
- _CH = retraceWait;
- _DI = t_offset;
- _DS = t_segment;
- if (_DH)
- {
- _CL = 4;
- if (_CH != 0)
- {
- asm mov dx, 3DAH // Get address of Motorola 6845 to DX
-
- waitL1: asm in al, dx
- asm rcr al, 1
- asm jc waitL1
-
- asm cli
-
- waitH1: asm in al, dx
- asm rcr al, 1
- asm jnc waitH1
-
- asm mov bl, BYTE PTR [di + 1]
- asm ror bl, cl
-
- waitL2: asm in al, dx
- asm rcr al, 1
- asm jc waitL2
-
- waitH2: asm in al, dx
- asm rcr al, 1
- asm jnc waitH2
-
- asm mov BYTE PTR [di + 1], bl
- }
- else
- asm ror BYTE PTR [di + 1], cl
- }
- else
- {
- asm or ch, ch
- asm jz do_xor
-
- asm mov dx, 3DAH // Get address of Motorola 6845 to DX
-
- waitL3: asm in al, dx
- asm rcr al, 1
- asm jc waitL3
-
- asm cli
-
- waitH3: asm in al, dx
- asm rcr al, 1
- asm jnc waitH3
-
- do_xor: asm xor BYTE PTR [di + 1], 0FFH
- }
- asm sti
- asm pop ds
- }
-