home *** CD-ROM | disk | FTP | other *** search
- // Zinc Interface Library - TEXT1.CPP
- // COPYRIGHT (C) 1990, 1991. All Rights Reserved.
- // Zinc Software Incorporated. Pleasant Grove, Utah USA
-
- #pragma inline
-
- #include "ui_win.hpp"
- #include <ctype.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #define PIXEL_BORDER 2
- #define TAB_STOP 8
- const short MAX_WIDTH = 128;
-
- #define TAB 9
- #define LF 10
- #define CR 13
-
- USHORT LineChanged(char *newLine, char *oldLine, int width);
-
- #if 0
- char *AdvanceLine(char *ptr, USHORT numLines, int col, USHORT *actual,
- int width)
- {
- USHORT count = 0;
-
- while (numLines-- && *ptr)
- {
- char *row_start = ptr;
- while (col < width && *ptr)
- {
- if (*ptr == '\t')
- {
- col = (col + TAB_STOP) & ~(TAB_STOP - 1);
- ptr++;
- }
- else if (*ptr == '\r' || *ptr == '\n')
- {
- ptr++;
- if (*(ptr - 1) == '\r' && *ptr == '\n')
- ptr++;
- count++;
- break;
- }
- else {
- ptr++;
- col++;
- }
- }
- if (col >= width) // Check for word wrap.
- {
- char *rover = ptr;
- count++;
- while (rover > row_start && *(rover - 1) != '\t' &&
- *(rover - 1) != ' ')
- rover--;
- if (rover > row_start)
- ptr = rover;
- }
- col = 0;
- }
- if (actual)
- *actual = count;
- return ptr;
- }
- #endif
-
- char *AdvanceLine(char *linePtr, USHORT numLines, int col, USHORT *actual,
- int width)
- {
- _CX = numLines;
- _DX = 0;
- _BL = col;
- _BH = width;
- #if sizeof(linePtr) == 4
- asm push ds
- asm lds si, linePtr
- #else
- asm mov si, linePtr
- #endif
- asm push bp
- asm jmp short whileNumLines
-
- zeroColumn:
- asm mov bl, 0
-
- whileNumLines:
- asm jcxz storeCount
- asm dec cx
-
- asm mov bp, si // BP = row_start
-
- whileSameLine:
- asm cmp bl, bh
- asm jae checkWrap
-
- asm lodsb
- asm cmp al, CR
- asm jbe isCtrl
-
- isReg: asm inc bl
- asm jmp whileSameLine
-
- isCtrl: asm je isCr
-
- asm cmp al, LF
- asm je isLf
-
- asm or al, al
- asm je isNull
-
- asm cmp al, TAB
- asm jne isReg
-
- isTab: asm add bl, TAB_STOP
- asm and bl, NOT (TAB_STOP - 1)
- asm jmp whileSameLine
-
- isCr: asm cmp BYTE PTR [si], LF
- asm jne isLf
-
- asm inc si
-
- isLf: asm inc dx
- asm jmp short checkWrap
-
- isNull: asm dec si
-
- checkWrap:
- asm cmp bl, bh
- asm jb zeroColumn
-
- asm mov di, si // DI = rover
- asm inc dx // count++
-
- wrap: asm cmp di, bp
- asm jbe zeroColumn
-
- asm mov al, [di - 1]
- asm cmp al, TAB
- asm je chkPtr
-
- asm cmp al, ' '
- asm je chkPtr
-
- asm dec di
- asm jmp wrap
-
- chkPtr: asm cmp di, bp
- asm jbe zeroColumn
-
- asm mov si, di
- asm jmp zeroColumn
-
- storeCount:
- asm pop bp
- if (actual)
- *actual = _DX;
- asm mov WORD PTR linePtr, si
- #if sizeof(linePtr) == 4
- asm mov WORD PTR linePtr + 2, ds
- asm pop ds
- #endif
- return linePtr;
- }
-
- char *UIW_TEXT::AdvanceColumns(char *ptr, int num_cols, int *result_col)
- {
- char *nextLine;
- int col = 0;
- USHORT count;
-
- nextLine = AdvanceLine(ptr, 1, 0, &count, width);
- if (count == 0)
- nextLine++; // Allow stopping on the trailing null.
- while (col < num_cols && ptr < nextLine - 1 && *ptr != '\r' && *ptr != '\n')
- {
- if (*ptr == '\t')
- {
- col = (col + TAB_STOP) & ~(TAB_STOP - 1);
- ptr++;
- }
- else
- {
- ptr++;
- col++;
- }
- }
- *result_col = col;
- return ptr;
- }
-
- void UIW_TEXT::BackspaceKey()
- {
- if (cursor > text)
- {
- LeftArrow();
- DeleteBlock(cursor, (*cursor == '\r' && *(cursor + 1) == '\n') ? 2 : 1);
- }
- }
-
- void UIW_TEXT::ComputeMousePosition(int mouse_col, int mouse_row)
- {
- char *ptr = screenTop;
- int row = 0;
- int col = 0;
- while (*ptr && row <= mouse_row)
- {
- USHORT count;
- char *nextLine = AdvanceLine(ptr, 1, 0, &count, width);
- while (*ptr && *ptr != '\r' && *ptr != '\n' && ptr < nextLine)
- {
- if (row == mouse_row && col >= mouse_col)
- break;
- if (*ptr == '\t')
- {
- col = (col + TAB_STOP) & ~(TAB_STOP - 1);
- ptr++;
- }
- else if (*ptr == '\0' || *ptr == '\r' || *ptr == '\n')
- ;
- else
- {
- col++;
- ptr++;
- }
- }
- if (row == mouse_row && col >= mouse_col)
- break;
- row += count;
- if (count)
- col = 0;
- if (row > mouse_row)
- break;
- ptr = nextLine;
- }
- if (row == mouse_row && col >= mouse_col || row > mouse_row)
- cursor = ptr;
- }
-
- void UIW_TEXT::ComputeRegion(int ccode, UI_REGION ®ion, UI_PALETTE *palette)
- {
- UI_WINDOW_OBJECT::Border(ccode, region, palette);
- pixelBorder = 0;
- if (!display->isText && region.bottom - region.top > display->cellHeight)
- {
- while (pixelBorder < PIXEL_BORDER && region.top < region.bottom - 1 &&
- region.left < region.right - 1)
- {
- region.top++;
- region.bottom--;
- region.left++;
- region.right--;
- pixelBorder++;
- }
- }
- else if (!display->isText)
- pixelBorder++;
- height = (region.bottom + 1 - region.top) / cellHeight;
- if (!display->isText)
- {
- int remainder = (region.bottom + 1 - region.top) % cellHeight;
- if (remainder >= display->TextHeight("W"))
- height++;
- }
- width = (region.right + 1 - region.left) / cellWidth;
- if (width > MAX_WIDTH)
- width = MAX_WIDTH;
- }
-
- void UIW_TEXT::ComputeScroll()
- {
- if (!previous)
- return;
-
- char *ptr = text;
- char *temp;
-
- if (FlagSet(woFlags, WOF_VIEW_ONLY))
- cursor = screenTop;
- USHORT count = 0;
- USHORT totalLines;
- while (ptr < cursor)
- {
- temp = AdvanceLine(ptr, 1, cursorCol, &totalLines, width);
- if (temp != ptr)
- ptr = temp;
- else
- break;
- count += totalLines;
- }
- if (ptr != cursor && !FlagSet(woFlags, WOF_VIEW_ONLY))
- count--;
- AdvanceLine(text, 5000, 0, &totalLines, width);
- UI_EVENT event;
- event.type = S_SCROLL_VERTICAL_SET;
- event.scroll.current = count;
- event.scroll.showing = height;
- event.scroll.maximum = FlagSet(woFlags, WOF_VIEW_ONLY) ? totalLines - height + 1 : totalLines;
- if (event.scroll.maximum < event.scroll.showing)
- event.scroll.showing = event.scroll.maximum;
- Previous()->Event(event);
- event.type = S_SCROLL_HORIZONTAL_SET;
- event.scroll.current = event.scroll.showing = event.scroll.maximum = 1;
- Previous()->Event(event);
- }
-
- void UIW_TEXT::CopyBlock()
- {
- while (screenTop >= markStart && screenTop > text)
- screenTop = PreviousLine(screenTop, 1, 0, text);
-
- pasteLength = (int)(markTail - markStart);
- if (pasteBuffer)
- delete pasteBuffer;
- pasteBuffer = new char[pasteLength];
- memcpy(pasteBuffer, markStart, pasteLength);
-
- markedBlock = NULL;
- }
-
- void UIW_TEXT::DeleteBlock(char *block, USHORT length)
- {
- if (!length)
- return;
-
- pasteLength = length;
- if (pasteBuffer)
- delete pasteBuffer;
- pasteBuffer = new char[pasteLength];
- memcpy(pasteBuffer, block, pasteLength);
-
- woStatus |= WOS_CHANGED | WOS_NO_AUTO_CLEAR;
- strcpy(block, block + length);
- cursorDesiredCol = -1;
- cursor = block;
- markedBlock = NULL;
- }
-
- void UIW_TEXT::DeleteEol()
- {
- char *nextLine;
- char *rover;
- USHORT count;
-
- nextLine = AdvanceLine(cursor, 1, cursorCol, 0, width);
- rover = cursor;
- while (*rover && *rover != '\r' && *rover != '\n' && rover < nextLine)
- rover++;
- count = (USHORT) (rover - cursor);
- if (count)
- DeleteBlock(cursor, count);
- }
-
- void UIW_TEXT::DeleteWord()
- {
- char *ptr;
-
- if (NonWhiteSpace(*cursor) || *cursor == ' ')
- {
- if (*cursor == ' ')
- {
- if (cursor == text || WhiteSpace(*(cursor - 1)))
- {
- ptr = cursor;
- while (*ptr == ' ')
- ptr++;
- DeleteBlock(cursor, (USHORT) (ptr - cursor));
- return; /* NOTE: second return point here. */
- }
- WordTabLeft();
- }
- else
- {
- while (cursor > text && NonWhiteSpace(*(cursor - 1)))
- LeftArrow();
- }
- ptr = cursor;
- while (NonWhiteSpace(*ptr))
- ptr++;
- while (*ptr == ' ')
- ptr++;
- DeleteBlock(cursor, (USHORT) (ptr - cursor));
- }
- }
-
- void UIW_TEXT::EnterKey()
- {
- static char cr_lf[2] = { '\r', '\n' };
-
- if (strchr(cursor, '\0') < textTail - 1)
- InsertBlock(cursor, cr_lf, 2);
- }
-
- void UIW_TEXT::Home()
- {
- char *previousLine = PreviousLine(cursor, 1, cursorCol, text);
- cursor = (previousLine) ? AdvanceLine(previousLine, 1, 0, 0, width) : text;
- cursorDesiredCol = 0;
- }
-
- void UIW_TEXT::InsertBlock(char *insertPoint, char *block, USHORT length)
- {
- woStatus |= (WOS_CHANGED | WOS_NO_AUTO_CLEAR);
- memmove(insertPoint + length, insertPoint, strlen(insertPoint) + 1);
- memcpy(insertPoint, block, length);
- if (insertPoint == cursor)
- cursor += length;
- cursorDesiredCol = -1;
- }
-
- int UIW_TEXT::LastLine()
- {
- short col = cursorCol;
- char *ptr = cursor;
-
- while (col < width && *ptr && *ptr != '\r' && *ptr != '\n')
- {
- if (*ptr == '\t')
- {
- col = (col + TAB_STOP) & ~(TAB_STOP - 1);
- ptr++;
- }
- else
- {
- ptr++;
- col++;
- }
- }
- return (*ptr == '\0' ? TRUE : FALSE);
- }
-
- void UIW_TEXT::LeftArrow()
- {
- if (cursor > text)
- {
- cursor--;
- if (*cursor == '\n' && cursor > text && *(cursor - 1) == '\r')
- cursor--;
- if (cursor < screenTop)
- screenTop = PreviousLine(screenTop, 1, 0, text);
- cursorDesiredCol = -1;
- }
- }
-
- #pragma argsused
- void UIW_TEXT::MoveDown(USHORT numLines, int ccode)
- {
- char *nextLine;
- int col;
- int row;
-
- row = cursorRow;
- col = cursorCol;
- int totalLines = 0;
- int viewLines = 0;
- while (numLines--)
- {
- nextLine = AdvanceLine(cursor, 1, col, 0, width);
- if (*nextLine || (nextLine > cursor &&
- (*(nextLine - 1) == '\r' || *(nextLine - 1) == '\n')))
- {
- /* There is a line to advance to. */
- totalLines++;
- row++;
- cursor = AdvanceColumns(nextLine, cursorDesiredCol, &col);
- if (row >= height)
- {
- screenTop = AdvanceLine(screenTop, 1, 0, 0, width);
- viewLines++;
- row--;
- }
- }
- else
- break;
- }
- }
-
- #pragma argsused
- void UIW_TEXT::MoveUp(USHORT numLines, int ccode)
- {
- char *nextLine;
- int col;
-
- col = cursorCol;
- int totalLines = 0;
- int viewLines = 0;
- while (numLines--)
- {
- nextLine = PreviousLine(cursor, 1, col, text);
- if (nextLine)
- {
- totalLines++;
- cursor = AdvanceColumns(nextLine, cursorDesiredCol, &col);
- if (nextLine < screenTop)
- {
- screenTop = nextLine;
- viewLines++;
- }
- }
- else
- break;
- }
-
- if (previous && totalLines)
- {
- UI_WINDOW_OBJECT *object = Previous();
- UI_EVENT event;
- event.type = S_SCROLL_VERTICAL;
- event.scroll.delta = FlagSet(woFlags, WOF_VIEW_ONLY) ? viewLines : totalLines;
- object->Event(event);
- }
- }
-
- void UIW_TEXT::PasteBlock()
- {
- if (pasteBuffer && (!markedBlock || markedBlock == cursor) &&
- pasteLength <= textTail - strchr(cursor, '\0'))
- {
- markedBlock = 0;
- InsertBlock(cursor, pasteBuffer, pasteLength);
- }
- }
-
- char *UIW_TEXT::PreviousLine(char *line, USHORT numLines, int col, char *base)
- {
- char *base_line;
- char *rover;
- USHORT baseDelta;
- USHORT maxDelta;
- USHORT lineNum;
- USHORT count;
-
- baseDelta = (USHORT) (line - base);
- maxDelta = numLines * (width + 2) + col + 2;
- if (maxDelta < baseDelta)
- {
- rover = line - maxDelta;
- while (rover > base && *(rover - 1) != '\n' && *(rover - 1) != '\r')
- rover--;
- base_line = rover;
- }
- else
- base_line = base;
- rover = base_line;
- lineNum = 0;
- while (rover <= line)
- {
- rover = AdvanceLine(rover, 1, 0, &count, width);
- lineNum++;
- if (count == 0 && *rover == '\0')
- break;
- }
- if (lineNum < numLines + 1)
- return 0;
- else
- return AdvanceLine(base_line, lineNum - numLines - 1, 0, 0, width);
- }
-
- void UIW_TEXT::Redisplay(UI_REGION ®ion, int ccode)
- {
- USHORT count;
- char line[MAX_WIDTH];
- char xor[MAX_WIDTH];
- cursorRow = -1;
- if (FlagSet(woStatus, WOS_UNANSWERED))
- {
- text[0] = '\0';
- cursor = text;
- screenTop = text;
- textNull = text;
- markedBlock = 0;
- cursorDesiredCol = -1;
- }
- int newScreenSize = height * width;
- if (newScreenSize > screenSize)
- {
- if (screen)
- delete screen;
- screen = 0;
- }
- if (!screen)
- {
- screen = new char[newScreenSize];
- screenSize = newScreenSize;
- screenInvalid = TRUE;
- }
- if (screenInvalid)
- {
- memset(screen, '\1', screenSize);
- if (!display->isText)
- {
- UI_REGION border = region;
- UI_PALETTE tPalette = *lastPalette;
- tPalette.colorForeground = tPalette.colorBackground;
- tPalette.bwForeground = tPalette.bwBackground;
- tPalette.grayScaleForeground = tPalette.grayScaleBackground;
- for (int i = 0; i < pixelBorder; i++)
- {
- border.top--;
- border.bottom++;
- border.left--;
- border.right++;
- display->Rectangle(screenID, border, &tPalette);
- }
- }
- }
- SetMark();
- char *newMarkStart = 0;
- char *newMarkTail = 0;
- char *ptr = screenTop;
- int row = 0;
- int rowWidth = 0;
- if (markStart && ptr >= markStart)
- newMarkStart = screen;
- if (width <= 0)
- {
- if (!display->isText)
- display->Rectangle(screenID, region, lastPalette, 0, TRUE);
- return;
- }
-
- while (row < height)
- {
- int markLine = FALSE;
- int markLeft = width - 1;
- int markRight = 0;
- int col = 0;
- char *nextLine = AdvanceLine(ptr, 1, 0, &count, width);
- while (*ptr != '\r' && *ptr != '\n' && ptr < nextLine)
- {
- if (markedBlock)
- {
- if (ptr >= markStart && ptr < markTail)
- {
- if (ptr == markStart)
- newMarkStart = screen + rowWidth + col;
- markLine = TRUE;
- if (col < markLeft)
- markLeft = col;
- if (col > markRight)
- markRight = col;
- }
- else if (ptr == markTail)
- newMarkTail = screen + rowWidth + col;
- }
- if (ptr == cursor)
- {
- cursorRow = row;
- cursorCol = col;
- }
- if (*ptr == '\t')
- {
- int newCol = (col + TAB_STOP) & ~(TAB_STOP - 1);
- memset(&line[col], ' ', newCol - col);
- col = newCol;
- ptr++;
- }
- else
- line[col++] = *ptr++;
- }
- if (col > width) // Necessary due to TAB at end of line possibility.
- col = width;
- if (ptr == cursor && cursorRow == -1)
- {
- cursorRow = row;
- cursorCol = col;
- }
- memset(&line[col], '\0', width - col);
- if (ptr == markStart && !newMarkStart)
- newMarkStart = screen + rowWidth + col;
- else if (ptr == markTail && !newMarkTail)
- newMarkTail = screen + rowWidth + col;
- memset(xor, '\0', width);
- int nextRowWidth = rowWidth + width; // (row + 1) * width
- if (screenMarkStart && screenMarkStart < screen + nextRowWidth &&
- screenMarkTail > screen + rowWidth)
- {
- int lineStart = 0;
- if (screenMarkStart > screen + rowWidth)
- lineStart = (int) (screenMarkStart - (screen + rowWidth));
- int lineTail = Min(col, width);
- if (screenMarkTail < screen + nextRowWidth)
- lineTail = (int) (screenMarkTail - (screen + rowWidth));
- if (lineTail > lineStart)
- memset(&xor[lineStart], 1, lineTail - lineStart);
- }
- _DX = LineChanged(line, screen + rowWidth, width);
- if (_DX != 0xFFFF)
- {
- int leftCol = _DL;
- int rightCol = _DH;
- // Re-displaying will wipe out mark.
- memset(&xor[leftCol], '\0', rightCol + 1 - leftCol);
- if (!display->isText) // Pre-fill for graphics.
- {
- int topPixel = region.top + row * cellHeight;
- int bottomPixel = topPixel + cellHeight - 1;
- if (bottomPixel > true.bottom - pixelBorder)
- bottomPixel = true.bottom - pixelBorder;
- display->Rectangle(screenID, region.left + leftCol * cellWidth,
- topPixel, rightCol == width - 1 ? region.right :
- region.left + (rightCol + 1) * cellWidth - 1,
- bottomPixel, lastPalette, 0, TRUE);
- }
- display->Text(screenID, region.left + leftCol * cellWidth,
- region.top + row * cellHeight, &line[leftCol],
- lastPalette, rightCol + 1 - leftCol, FALSE);
- }
- if (markLine)
- {
- for (int i = markLeft; i <= markRight; i++)
- xor[i] ^= 1;
- }
- char *xorStart = xor;
- while ((xorStart = (char *) memchr(xorStart, '\1', (int) (xor + width - xorStart))) != 0)
- {
- int leftXor = (int) (xorStart - xor);
- int rightXor = leftXor;
- while (rightXor < width - 1 && xor[rightXor + 1])
- rightXor++;
- display->Text(screenID, region.left + leftXor * cellWidth,
- region.top + row * cellHeight, NULL, _xorPalette,
- rightXor + 1 - leftXor, TRUE, TRUE);
- xorStart = xor + rightXor + 1;
- }
- ptr = nextLine;
- row += count;
- if (count)
- col = 0;
- if (!newMarkStart && ptr == markStart)
- newMarkStart = screen + row * width + col;
- else if (!newMarkTail && ptr == markTail)
- newMarkTail = screen + row * width + col;
- if (ptr == cursor && cursorRow == -1)
- {
- cursorRow = row;
- cursorCol = col;
- }
- if (!count)
- row++;
- rowWidth += width;
- }
-
- if (ptr <= markTail && !newMarkTail)
- newMarkTail = screen + rowWidth; // Point just past end of screen.
- if (screenInvalid)
- {
- screenInvalid = FALSE;
- if (!display->isText &&
- region.top + height * cellHeight <= region.bottom)
- display->Rectangle(screenID, region.left,
- region.top + height * cellHeight, region.right,
- region.bottom, lastPalette, 0, TRUE);
- }
- if (cursorRow == -1)
- {
- cursorRow = 0;
- cursorCol = 0;
- }
- if (cursorDesiredCol == -1)
- cursorDesiredCol = cursorCol;
- screenMarkStart = newMarkStart;
- screenMarkTail = newMarkTail;
- if (ccode != S_DISPLAY_INACTIVE)
- UpdateCursor(region);
- }
-
- void UIW_TEXT::RegularKey(USHORT key)
- {
- if (FlagSet(woFlags, WOF_AUTO_CLEAR) &&
- !FlagSet(woStatus, WOS_NO_AUTO_CLEAR) && cursor == text && *text)
- DeleteBlock(text, strlen(text));
- if (insertMode || *cursor == '\r' || *cursor == '\n' || *cursor == '\0')
- {
- if (strchr(cursor, '\0') < textTail)
- InsertBlock(cursor, (char *)&key, 1);
- }
- else if (cursor < textTail)
- ReplaceChar(cursor, key);
- }
-
- void UIW_TEXT::ReplaceChar(char *buff, USHORT key)
- {
- woStatus |= WOS_CHANGED | WOS_NO_AUTO_CLEAR;
- *buff = key;
- if (buff == cursor)
- cursor++;
- cursorDesiredCol = -1;
- }
-
- void UIW_TEXT::UpdateCursor(UI_REGION ®ion)
- {
- if (FlagSet(woStatus, WOS_CURRENT) && !FlagSet(woFlags, WOF_VIEW_ONLY) &&
- !FlagSet(woAdvancedStatus, WOAS_TOO_SMALL))
- {
- int col = cursorCol * cellWidth;
- int row = cursorRow * cellHeight;
-
- if (region.left + col >= 0 && region.left + col < display->columns &&
- region.top + row >= 0 && region.top + row < display->lines)
- {
- eventManager->DevicePosition(E_CURSOR, region.left + col, region.top + row);
- eventManager->DeviceState(E_CURSOR,
- insertMode ? DC_INSERT : DC_OVERTYPE);
- }
- }
- }
-
- void UIW_TEXT::WordTabLeft()
- {
- while (cursor > text && WhiteSpace(*(cursor - 1)))
- cursor--;
- while (cursor > text && NonWhiteSpace(*(cursor - 1)))
- cursor--;
- while (cursor < screenTop)
- screenTop = PreviousLine(screenTop, 1, 0, text);
- cursorDesiredCol = -1;
- }
-
-