home *** CD-ROM | disk | FTP | other *** search
- // Zinc Interface Library - STRING1.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 <string.h>
-
- #if 0
-
- // Original C version of the "LineChanged" routine below.
- USHORT LineChanged(char *newLine, char *oldLine, int width)
- {
- if (width > 0)
- {
- int leftCol = 0;
- int rightCol = width - 1;
- while (leftCol <= rightCol && newLine[leftCol] == oldLine[leftCol])
- leftCol++;
- while (leftCol <= rightCol && newLine[rightCol] == oldLine[rightCol])
- rightCol--;
- if (leftCol <= rightCol)
- {
- memcpy(&oldLine[leftCol], &newLine[leftCol], rightCol + 1 - leftCol);
- return leftCol + (rightCol << 8);
- }
- }
- return 0xFFFF;
- }
- #endif
-
- /* LineChanged -
- * Compare a line of text about to be written to the screen with the
- * saved copy of that line to see if there are any changes. If so,
- * return the leftmost column of the changed area in the low order
- * byte, and the rightmost column of the changed area in the high order
- * byte. If the line has not changed, return -1 (0xFFFF).
- */
- USHORT LineChanged(char *newLine, char *oldLine, int width)
- {
- #if sizeof(newLine) == 4
- asm push ds
- asm lds si, newLine
- asm les di, oldLine
- #else
- asm mov si, newLine
- asm push ds
- asm pop es
- asm mov di, oldLine
- #endif
- asm mov ax, 0FFFFH // Preset for "no change" (-1) return.
- asm mov cx, width
- asm cmp cx, 0
- asm jle done
-
- asm repe cmpsb
- asm je done // Return -1 if no change in the line.
-
- asm dec si // Point back to first non-match
- asm dec di // ""
- asm mov bx, si // Save copy of ptr to first non-match
- asm add si, cx // Point to last character
- asm add di, cx // " " " "
- asm mov cx, width
- asm std
- asm repe cmpsb
- asm inc si // Point to last non-match
- asm inc di // " " " "
- asm mov ah, cl // Save copy of rightCol in AH
- asm mov cx, si
- asm inc cx
- asm sub cx, bx // CX has number of different bytes.
- asm mov al, ah
- asm inc al
- asm sub al, cl // AL = leftCol = rightCol + 1 - count
- asm rep movsb // Update copy of old line
- asm cld
-
- done:
- #if sizeof(newLine) == 4
- asm pop ds
- #endif
- return _AX;
- }
-
- void UIW_STRING::DataSet(char *newText, short maxLength)
- {
- if (newText)
- {
- short oldMaxLength = (short)(textTail + 1 - text);
- if (FlagSet(woFlags, WOF_NO_ALLOCATE_DATA))
- text = newText;
- else
- {
- if (maxLength != -1 && maxLength > oldMaxLength)
- {
- delete text;
- text = new char[maxLength];
- }
- int srcLen = strlen(newText) + 1;
- int realMaxLength = (maxLength == -1) ? oldMaxLength : maxLength;
- memcpy(text, newText, Min(srcLen, realMaxLength));
- }
- if (maxLength != -1)
- textTail = text + maxLength - 1;
- else
- textTail = text + oldMaxLength - 1;
- *textTail = '\0'; // Insure trailing null.
- screenTop = text;
- cursor = text;
- markedBlock = 0;
- }
- UI_WINDOW_OBJECT::Redisplay(FALSE);
- }
-
- void UIW_STRING::BackspaceKey()
- {
- if (cursor > text)
- {
- LeftArrow();
- DeleteBlock(cursor, 1);
- CheckLeftScroll();
- }
- }
-
- int UIW_STRING::CalcLeading(int width)
- {
- int textLen = strlen(screenTop);
- int leading = 0;
- if (textLen < fieldWidth - 1)
- {
- if (woFlags & WOF_JUSTIFY_CENTER)
- leading = Min((fieldWidth - 1 - textLen) / 2, width);
- else if (woFlags & WOF_JUSTIFY_RIGHT)
- leading = Min(fieldWidth - 1 - textLen, width);
- }
- return leading;
- }
-
- void UIW_STRING::CheckLeftScroll()
- {
- if (cursor <= screenTop && screenTop > text)
- screenTop = Max(text, cursor - fieldWidth / 3);
- }
-
- void UIW_STRING::CheckRightScroll()
- {
- if (cursor - screenTop >= fieldWidth)
- {
- char *maxScreenTop = textTail + 1 - fieldWidth;
- screenTop = Min(maxScreenTop, cursor + 1 - fieldWidth + fieldWidth / 3);
- }
- }
-
- void UIW_STRING::CopyBlock()
- {
- if (screenTop >= markStart && screenTop > text)
- screenTop = markStart;
-
- pasteLength = (int)(markTail - markStart);
- if (pasteBuffer)
- delete pasteBuffer;
- pasteBuffer = new char[pasteLength];
- memcpy(pasteBuffer, markStart, pasteLength);
-
- markedBlock = NULL;
- }
-
- void UIW_STRING::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;
- memmove(block, block + length, (size_t)(textNull + 1 - (block + length)));
- textNull -= length;
- cursor = block;
- markedBlock = NULL;
- }
-
- void UIW_STRING::DeleteEol()
- {
- char *rover;
- USHORT count;
-
- rover = strchr(cursor, '\0');
- count = (USHORT) (rover - cursor);
- if (count)
- DeleteBlock(cursor, count);
- }
-
- void UIW_STRING::DeleteWord()
- {
- char *ptr;
-
- if (*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_STRING::InsertBlock(char *insert_point, char *block, USHORT length)
- {
- if (length)
- {
- woStatus |= WOS_CHANGED | WOS_NO_AUTO_CLEAR;
- memmove(insert_point + length, insert_point,
- (size_t) (textNull + 1 - insert_point) );
- memcpy(insert_point, block, length);
- textNull += length;
- if (insert_point == cursor)
- cursor += length;
- }
- }
-
- void UIW_STRING::LeftArrow()
- {
- if (cursor > text)
- {
- cursor--;
- if (cursor < screenTop)
- screenTop--;
- }
- }
-
- void UIW_STRING::PasteBlock()
- {
- if (pasteBuffer && !markedBlock &&
- pasteLength <= textTail - textNull)
- InsertBlock(cursor, pasteBuffer, pasteLength);
- }
-
- void UIW_STRING::Redisplay(int ccode)
- {
- UI_REGION region;
- UI_WINDOW_OBJECT::Border(0, region, 0);
- short cellWidth = display->TextWidth("W");
- short cellHeight = display->TextHeight("W");
- short width = (region.right + 1 - region.left) / cellWidth;
- char line[133];
- char xor[133];
- if (FlagSet(woStatus, WOS_UNANSWERED))
- {
- text[0] = '\0';
- cursor = text;
- screenTop = text;
- textNull = text;
- markedBlock = 0;
- }
- int newScreenSize = 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);
- char *newMarkStart = 0;
- char *newMarkTail = 0;
- char *ptr = screenTop;
- int markLine = FALSE;
- int markLeft = width - 1;
- int textLen = strlen(screenTop);
- int leading = CalcLeading(width);
- textLen = Min(textLen, width - leading);
- memset(line, ' ', leading);
- int col = leading;
- int markRight = col;
- if (width <= 0)
- {
- if (!display->isText)
- display->Rectangle(screenID, region, lastPalette, 0, TRUE);
- }
- else
- {
- while (*ptr && col < width)
- {
- if (markedBlock)
- {
- if (ptr >= markStart && ptr < markTail)
- {
- if (ptr == markStart)
- newMarkStart = screen + col;
- markLine = TRUE;
- if (col < markLeft)
- markLeft = col;
- if (col > markRight)
- markRight = col;
- }
- else if (ptr == markTail)
- newMarkTail = screen + col;
- }
- line[col++] = *ptr++;
- }
- memset(&line[col], '\0', width - col);
- if (ptr == markStart && !newMarkStart)
- newMarkStart = screen + col;
- else if (ptr == markTail && !newMarkTail)
- newMarkTail = screen + col;
- memset(xor, '\0', width);
- if (screenMarkStart && screenMarkStart < screen + width &&
- screenMarkTail > screen)
- {
- int lineStart = 0;
- if (screenMarkStart > screen)
- lineStart = (int) (screenMarkStart - screen);
- int lineTail = Min(col, width);
- if (screenMarkTail < screen + width)
- lineTail = (int) (screenMarkTail - screen);
- memset(&xor[lineStart], '\1', lineTail - lineStart);
- }
- int vertOffset = VerticalCenterOffset(®ion);
- if (region.bottom >= region.top + cellHeight - 1)
- {
- _DX = LineChanged(line, screen, 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.
- {
- display->Rectangle(screenID,
- region.left + leftCol * cellWidth, region.top,
- rightCol == width - 1 ? region.right :
- region.left + (rightCol + 1) * cellWidth - 1,
- region.bottom, lastPalette, 0, TRUE);
- }
- display->Text(screenID,
- region.left + leftCol * cellWidth,
- region.top + vertOffset, &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 + vertOffset, NULL, _xorPalette,
- rightXor + 1 - leftXor, TRUE, TRUE);
- xorStart = xor + rightXor + 1;
- }
- if (!newMarkStart && ptr == markStart)
- newMarkStart = screen + col;
- else if (!newMarkTail && ptr == markTail)
- newMarkTail = screen + col;
- }
- else if (screenInvalid)
- {
- // We are in graphics mode with not enough height to display text.
- display->Rectangle(screenID, region, lastPalette, 0, TRUE);
- }
- screenInvalid = FALSE;
- screenMarkStart = newMarkStart;
- screenMarkTail = newMarkTail;
- if (ccode != S_DISPLAY_INACTIVE)
- UpdateCursor(region, width);
- }
- }
-
- void UIW_STRING::RegularKey(USHORT key)
- {
- if (FlagSet(woFlags, WOF_AUTO_CLEAR) &&
- !FlagSet(woStatus, WOS_NO_AUTO_CLEAR) && cursor == text && *text)
- {
- DeleteBlock(text, strlen(text));
- textNull = text;
- }
- if (insertMode || cursor == textNull)
- {
- if (textNull < textTail)
- InsertBlock(cursor, (char *) &key, 1);
- }
- else if (cursor < textTail)
- ReplaceChar(cursor, key);
- CheckRightScroll();
- }
-
- void UIW_STRING::ReplaceChar(char *buff, USHORT key)
- {
- woStatus |= WOS_CHANGED | WOS_NO_AUTO_CLEAR;
- *buff = key;
- if (buff == cursor)
- cursor++;
- }
-
- void UIW_STRING::SetMark()
- {
- markStart = markTail = 0;
- if (markedBlock)
- {
- if (markedBlock > cursor)
- {
- markStart = cursor;
- markTail = markedBlock;
- }
- else if (markedBlock < cursor)
- {
- markStart = markedBlock;
- markTail = cursor;
- }
- }
- }
-
- void UIW_STRING::UpdateCursor(UI_REGION ®ion, int width)
- {
- int cursorColumn = (int)(cursor - screenTop);
- int leading = CalcLeading(width);
- int trueColumn = region.left + (leading + cursorColumn) * display->TextWidth("W");
- if ( FlagSet(woStatus, WOS_CURRENT) && !FlagSet(woFlags, WOF_VIEW_ONLY) &&
- !FlagSet(woAdvancedStatus, WOAS_TOO_SMALL) &&
- trueColumn >= 0 &&
- trueColumn < display->columns && region.top >= 0 &&
- region.top < display->lines && leading + cursorColumn < width)
- {
- eventManager->DevicePosition(E_CURSOR, trueColumn, region.top + VerticalCenterOffset(®ion) );
- eventManager->DeviceState(E_CURSOR, (insertMode ? DC_INSERT : DC_OVERTYPE));
- }
- }
-
- int UIW_STRING::VerticalCenterOffset(UI_REGION *region)
- {
- if (display->isText) // Center text vertically (if graphics).
- return 0;
- else
- return (region->bottom + 2 - region->top - display->TextHeight("W")) / 2;
- }
-
- void UIW_STRING::WordTabLeft()
- {
- while ( cursor > text && WhiteSpace( *(cursor - 1) ) )
- cursor--;
- while ( cursor > text && NonWhiteSpace( *(cursor - 1) ) )
- cursor--;
- if (cursor < screenTop)
- screenTop = cursor;
- }
-
-