diff options
Diffstat (limited to 'sigalatvision/lib/asm.cc')
-rw-r--r-- | sigalatvision/lib/asm.cc | 903 |
1 files changed, 903 insertions, 0 deletions
diff --git a/sigalatvision/lib/asm.cc b/sigalatvision/lib/asm.cc new file mode 100644 index 0000000..937ad2a --- /dev/null +++ b/sigalatvision/lib/asm.cc @@ -0,0 +1,903 @@ +/* + * asm.cc + * + * Turbo Vision - Version 2.0 + * + * All the assembly functions are converted in C/C++ and placed here. + * This code was originally written by: + * - Tommy Andreasen + * - J”rn Sierwald + * + * Modified by Sergio Sigala <sergio@sigala.it> + * + * WARNING: very dirty code here... but it works :-) + */ + +#define Uses_TEditor +#define Uses_TEvent +#define Uses_TFrame +#define Uses_TGroup +#define Uses_TPoint +#define Uses_TRect +#define Uses_TScreen +#define Uses_TTerminal +#define Uses_TView +#include <tvision/tv.h> + +#include <ctype.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <config.h> /* configuration file */ + +#ifdef HAVE_NCURSES_H +#include <ncurses.h> +#else +#include <curses.h> +#endif + +#ifdef ENABLE_VCS +extern int vcsFd; /* virtual console system descriptor */ +#endif + +/* + * SS: this code is used to refresh the screen only if strictly necessary. + * Date: Mon Jun 23 10:26:09 MET DST 1997 + */ +static int lockRefresh = 0; + +inline void doRefresh(TView *p) +{ +#ifdef ENABLE_VCS + if (vcsFd >= 0) return; /* refresh is not necessary */ +#endif + if (lockRefresh != 0) return; /* we can't do any refresh */ + if (p->owner != NULL && + p->owner->lockFlag) return; /* the owner is locked */ + refresh(); +} + +struct StaticVars1 { + ushort *buf; +}; + +struct StaticVars2 { + TView* target; + short offset; + short y; +}; + +static StaticVars2 staticVars2; + +int countLines( void *buf, size_t count ) +{ + int anzahl=0; + char *str=(char*) buf; + for (unsigned int i=0; i<count; i++) { + if (*(str++)== '\n') anzahl++; + }; + return anzahl; +} + +// These Routines are taken from Rogue Wave Tools++ +size_t scan( const void *block, size_t size, const char *str ) +{ + const long q = 33554393L; + const long q32 = q<<5; + + int testLength = size; + int patternLength = strlen(str); + + if (patternLength <= 0) return UINT_MAX; //SS: nothing to search + if( testLength < patternLength) return UINT_MAX; + + long patternHash = 0; + long testHash = 0; + + register const char* testP= (const char*)block; + register const char* patP = str; + register long x = 1; + int i = patternLength-1; + while(i--) x = (x<<5)%q; + + for (i=0; i<patternLength; i++) { + patternHash = ( (patternHash<<5) + *patP++ ) % q; + testHash = ( (testHash <<5) + *testP++ ) % q; + } + + testP = (const char*)block; + const char* end = testP + testLength - patternLength; + + while (1) { + + if(testHash == patternHash) + return testP-(const char*)block; + + if (testP >= end) break; + + // Advance & calculate the new hash value: + testHash = ( testHash + q32 - *testP * x ) % q; + testHash = ( (testHash<<5) + *(patternLength + testP++) ) % q; + } + return UINT_MAX; // Not found. + +}; + +size_t iScan( const void *block, size_t size, const char *str ) +{ + const long q = 33554393L; + const long q32 = q<<5; + + int testLength = size; + int patternLength = strlen(str); + + if (patternLength <= 0) return UINT_MAX; //SS: nothing to search + if( testLength < patternLength) return UINT_MAX; + + long patternHash = 0; + long testHash = 0; + + register const char* testP= (const char*)block; + register const char* patP = str; + register long x = 1; + int i = patternLength-1; + while(i--) x = (x<<5)%q; + + for (i=0; i<patternLength; i++) { + patternHash = ( (patternHash<<5) + toupper(*patP++) ) % q; + testHash = ( (testHash <<5) + toupper(*testP++) ) % q; + } + + testP = (const char*)block; + const char* end = testP + testLength - patternLength; + + while (1) { + + if(testHash == patternHash) + return testP-(const char*)block; + + if (testP >= end) break; + + // Advance & calculate the new hash value: + testHash = ( testHash + q32 - toupper(*testP) * x ) % q; + testHash = ( (testHash<<5) + toupper(*(patternLength + testP++)) ) % q; + } + return UINT_MAX; // Not found. +}; + +// edits.cpp defines functions previously found in edits.asm +// +// This file written by J”rn Sierwald based on a file +// written by Tommy Andreasen + +char TEditor::bufChar( uint p ) +{ + return buffer[p + ((p >= curPtr) ? gapLen : 0)]; +} + +uint TEditor::bufPtr( uint p ) +{ + return (p >= curPtr) ? p + gapLen : p; +} + +#if 0 +void TEditor::formatLine( void *DrawBuf, uint LinePtr, + int Width, ushort Color ) +{ + uint p = LinePtr; + while ((p < curPtr) && (buffer[p] != 0x0D) && (p - LinePtr <= Width)) + { + ((ushort *) DrawBuf) [p - LinePtr] = buffer[p] + ((Color & 0xFF) << 8); + p++; + } + + if (p >= curPtr) + { + p += gapLen; + + while ((p < bufSize) && (buffer[p] != 0x0D) && + (p - gapLen - LinePtr <= Width)) + { + ((ushort *) DrawBuf) [p - gapLen - LinePtr] = + buffer[p] + ((Color & 0xFF) << 8); + p++; + } + } else + p += gapLen; + + while (p - gapLen - LinePtr <= Width) + { + ((ushort *) DrawBuf) [p - gapLen - LinePtr] = + ' ' + ((Color & 0xFF) << 8); + p++; + } +} +#endif + +void TEditor::formatLine( void *DrawBuf, uint LinePtr, + int Width, ushort Color ) +{ + ushort i = 0; // index in the DrawBuf + size_t p = LinePtr; // index in the Buffer + ushort curColor; + + /* draw the first part of the buffer */ + + while ((p < curPtr) && (buffer[p] != '\n') && (i <= Width)) { + curColor = (p>=selStart && p<selEnd) ? (Color & 0xFF00) : + ((Color & 0xFF) << 8); + if (buffer[p] == 0x9) { + do { + ((ushort *) DrawBuf) [i] = ' ' + curColor; + i++; + } while ((i % 8) && (i <= Width)); + p++; + } else { + ((ushort *) DrawBuf) [i] = curColor | (uchar)buffer[p]; + p++; i++; + } + } + + /* draw the second part of the buffer */ + + if (p >= curPtr) + { + p += gapLen; + + while ((p < bufSize) && (buffer[p] != '\n') && (i <= Width)) + { + curColor = (p>=selStart && p<selEnd) ? (Color & 0xFF00) : + ((Color & 0xFF) << 8); + if (buffer[p] == 0x9) { + do { + ((ushort *) DrawBuf) [i] = ' ' + curColor; + i++; + } while ((i % 8) && (i <= Width)); + p++; + } else { + ((ushort *) DrawBuf) [i] = curColor | (uchar)buffer[p]; + p++; i++; + } + } + } +// } else +// p += gapLen; /* XXX */ + + /* add some trailing spaces to fill the last part of the line */ + + while (i < Width) //buffer overflow problem fixed + { + curColor = (p>=selStart && p<selEnd) ? (Color & 0xFF00) : + ((Color & 0xFF) << 8); + ((ushort *) DrawBuf) [i] = ' ' + curColor; +// p++; i++; /* XXX */ + i++; + } +} + +uint TEditor::lineEnd( uint p ) +{ +/* + while (p < curPtr) + if (buffer[p] == 0x0D) + return p; + else + p++; + + if (curPtr == bufLen) + return curPtr; + + while (p + gapLen < bufLen) + if (buffer[p + gapLen] == 0x0D) + return p; + else + p++; + + return p; +*/ + if (p < curPtr) + { + /* SS: changed */ + + while (p < curPtr) + if (buffer[p] == '\n') + return p; + else + p++; + + if (curPtr == bufLen) + return bufLen; + + + } + else + { + if (p == bufLen) + return bufLen; + } + +/* SS: changed */ + + while (p + gapLen < bufSize) + if (buffer[p + gapLen] == '\n') + return p; + else + p++; + + return p; + +} + +uint TEditor::lineStart( uint p ) +{ +/* + while (p - gapLen > curPtr) + if (buffer[--p + gapLen] == 0x0D) + return p + 2; + + if (curPtr == 0) + return 0; + + while (p > 0) + if (buffer[--p] == 0x0D) + return p + 2; + + return 0; +*/ +/* SS: changed */ + + while (p > curPtr) + if (buffer[--p + gapLen] == '\n') + return p + 1; + + if (curPtr == 0) + return 0; + +/* SS: changed */ + + while (p > 0) + if (buffer[--p] == '\n') + return p + 1; + + return 0; +} + +uint TEditor::nextChar( uint p ) +{ + if (p == bufLen) return p; + + /* SS: changed */ + + return ++p; +} + +uint TEditor::prevChar( uint p ) +{ + if (p == 0) return p; + + /* SS: changed */ + + return --p; +} + +/*------------------------------------------------------------*/ +/* filename - exposed.cpp */ +/* */ +/* function(s) */ +/* Tview exposed member function */ +/*------------------------------------------------------------*/ + +/*------------------------------------------------------------*/ +/* */ +/* Turbo Vision - Version 1.0 */ +/* Copyright (c) 1991 by Borland International */ +/* All Rights Reserved. */ +/* */ +/* This file Copyright (c) 1993 by J”rn Sierwald */ +/* */ +/* */ +/*------------------------------------------------------------*/ + +int TView::exposedRec1(short x1, short x2, TView* p ) { + while (1) { +/*20*/ + p=p->next; + if (p==staticVars2.target) { // alle durch + return exposedRec2( x1, x2, p->owner ); + }; + if ( !(p->state & sfVisible) || staticVars2.y<p->origin.y) continue; // keine Verdeckung + + if ( staticVars2.y<p->origin.y+p->size.y ) { + // šberdeckung m”glich. + if (x1<p->origin.x) { // f„ngt links vom Object an. + if (x2<=p->origin.x) continue; // links vorbei + if (x2>p->origin.x+p->size.x) { + if (exposedRec1( x1, p->origin.x, p )) return 1; + x1=p->origin.x+p->size.x; + } + else + x2=p->origin.x; + } else { + if ( x1<p->origin.x+p->size.x ) x1=p->origin.x+p->size.x; + if ( x1>=x2 ) return 0; // komplett verdeckt. + }; + }; + + }; // while + +} + +int TView::exposedRec2( short x1, short x2, TView* p ) { + + if (!(p->state & sfVisible)) return 0; + if ( !p->owner || p->owner->buffer ) return 1; + + StaticVars2 savedStatics = staticVars2; + + staticVars2.y += p->origin.y; + x1 += p->origin.x; + x2 += p->origin.x; + staticVars2.target=p; + + TGroup* g=p->owner; + if (staticVars2.y<g->clip.a.y || staticVars2.y >= g->clip.b.y) { + staticVars2 = savedStatics; + return 0; + }; + if (x1<g->clip.a.x) x1 = g->clip.a.x; + if (x2>g->clip.b.x) x2 = g->clip.b.x; + if (x1>=x2) { + staticVars2 = savedStatics; + return 0; + }; + + int retValue = exposedRec1( x1, x2, g->last ); + staticVars2 = savedStatics; + return retValue; +} + +Boolean TView::exposed() { + if ( !(state & sfExposed) || size.x <= 0 || size.y <= 0 ) return Boolean(0); + for (short y=0; y<size.y; y++) { + staticVars2.y=y; + if (exposedRec2( 0, size.x, this )) return Boolean(1); + }; + return Boolean(0); +} + +/*------------------------------------------------------------*/ +/* filename - framelin.cpp */ +/* */ +/* function(s) */ +/* TFrame frameLine member function */ +/*------------------------------------------------------------*/ + +/*------------------------------------------------------------*/ +/* */ +/* Turbo Vision - Version 1.0 */ +/* Copyright (c) 1991 by Borland International */ +/* All Rights Reserved. */ +/* */ +/* This file Copyright (c) 1993 by J”rn Sierwald */ +/* */ +/* */ +/*------------------------------------------------------------*/ + +/* Erkl„rung der Mask: + + Bit 0 + | + Bit 3 - - Bit 1 + | + Bit 2 + +Wenn z.B. sichergestellt werden soll, dass eine linke obere Ecke im +Muster vorhanden ist, nimmt man : + mask |= 0x06 . +*/ + +void TFrame::frameLine( TDrawBuffer& frameBuf, short y, short n, uchar color ) +{ + unsigned char frameMask[maxViewWidth]; + short int i; + frameMask[0]=initFrame[n]; + for (i=1; i+1<size.x; i++) { + frameMask[i]=initFrame[n+1]; + }; + frameMask[size.x-1]=initFrame[n+2]; + + TView* p; + p=owner->last; + while (1) { + p=p->next; + if (p==this) break; + if ((p->options & ofFramed) && (p->state & sfVisible)) { + unsigned char mask1, mask2; + if (y+1<p->origin.y) continue; + else if (y+1==p->origin.y) { mask1=0x0A; mask2=0x06;} + else if (y==p->origin.y+p->size.y) { mask1=0x0A; mask2=0x03;} + else if (y<p->origin.y+p->size.y) { mask1=0; mask2=0x05;} + else continue; + unsigned short xMin=p->origin.x; + unsigned short xMax=p->origin.x+p->size.x; + if (xMin<1) xMin=1; + if (xMax>size.x-1) xMax=size.x-1; + if (xMax>xMin) { + if (mask1==0) { + frameMask[xMin-1] |= mask2; + frameMask[xMax] |= mask2; + } else { + frameMask[xMin-1] |= mask2; + frameMask[xMax] |= (mask2 ^ mask1); + for (i=xMin; i< xMax; i++) { + frameMask[i] |= mask1; + } + }; + }; + }; + }; // while + unsigned short* dest=frameBuf.data; + i=size.x; + short int i1=0; + while (i--) { + *dest++= ( ((unsigned short)color) << 8 ) + (unsigned char) frameChars[frameMask[i1]]; + i1++; + } /* endwhile */ +}; + +/*------------------------------------------------------------*/ +/* filename - tgrmv.cpp */ +/* */ +/* function(s) */ +/* TGroup removeView member function */ +/*------------------------------------------------------------*/ + +/*------------------------------------------------------------*/ +/* */ +/* Turbo Vision - Version 1.0 */ +/* Copyright (c) 1991 by Borland International */ +/* All Rights Reserved. */ +/* */ +/* This file Copyright (c) 1993 by J”rn Sierwald */ +/* */ +/* */ +/*------------------------------------------------------------*/ + +void TGroup::removeView( TView *p ) { + if (last) { + TView *cur=last; + while (1) { + if (p==cur->next) { + cur->next=p->next; + if (last==p) { + if (cur->next==p) last=0; + else last=cur; + break; + }; + }; + if (cur->next==last) break; + cur=cur->next; + }; + }; // endif +}; + +/*------------------------------------------------------------*/ +/* filename - tvcursor.cpp */ +/* */ +/* function(s) */ +/* Tview resetCursor member function */ +/*------------------------------------------------------------*/ + +/*------------------------------------------------------------*/ +/* */ +/* Turbo Vision - Version 1.0 */ +/* Copyright (c) 1991 by Borland International */ +/* All Rights Reserved. */ +/* */ +/* This file Copyright (c) 1993 by J”rn Sierwald */ +/* */ +/* */ +/*------------------------------------------------------------*/ + +void TView::resetCursor() { + TView *p,*p2; + TGroup *g; + TPoint cur; + if ((state & (sfVisible | sfCursorVis | sfFocused)) + == (sfVisible | sfCursorVis | sfFocused) ) + { + p=this; + cur=cursor; + while (1) { + if (!(cur.x>=0 && cur.x<p->size.x + && cur.y>=0 && cur.y<p->size.y)) { + break; + }; + cur.x += p->origin.x; + cur.y += p->origin.y; + p2 =p; + g=p->owner; + if (g==0) { + //cursor setzen + + /* + * SS: we should change the cursor size according to the sfCursorIns + * flag in the state variable: + * + * if (state & sfCursorIns) { + * setBigCursor + * } else { + * setSmallCursor + * } + * + * Is there a way to do it under linux ? + */ + TScreen::moveCursor(cur.x, cur.y); + TScreen::drawCursor(1); + return; + }; + if (!(g->state & sfVisible)) break; + p=g->last; + { + label1: + p=p->next; + if (p==p2) { // alle durchgesucht. + p=p->owner; + continue; + }; + if ((p->state & sfVisible) + && cur.x>=p->origin.x + && cur.x<p->size.x+p->origin.x + && cur.y>=p->origin.y + && cur.y<p->size.y+p->origin.y) { + break; // Cursor wird verdeckt. + }; + goto label1; + }; + }; + } + // no cursor, please. + TScreen::drawCursor(0); +} + +// TTPRVLNS.CPP +// Copyright 1994 by J”rn Sierwald +// +// C++ Version of ttprvlns.asm +// implementation of TTerminal::prevLines(...) +// +// "You don't need assembler to write obfuscated code." + +ushort TTerminal::prevLines(ushort pos, ushort lines ) { + if (lines==0) { bufInc(pos); bufInc(pos); return pos; }; + // I don't see the logic in the previous line. But that's what + // the .asm file says. + + if (pos==queBack) return queBack; // Nothing to do + + bufDec(pos); // pos might be pointing to a '\n' + + if (pos<queBack) { + while ( !( buffer[pos]=='\n' && !--lines ) && pos-- ); + if (lines) pos=bufSize-1; + }; + + if (lines) +/* SS: we should check if there is an available character before read it */ + while (pos > queBack && !( buffer[pos]=='\n' && !--lines )) + { + pos--; + } + + if (lines) + return queBack; + else + bufInc(pos); + + return pos; +}; + +// TVWRITE.CPP +// Copyright 1993,1994 by J”rn Sierwald +// +// C++ Version of tvwrite.asm +// +// It doesn't look beautiful, but what the heck.. + +extern TPoint shadowSize; +extern uchar shadowAttr; + +static StaticVars1 staticVars1; + +void TView::writeViewRec1(short x1, short x2, TView* p, int shadowCounter ) { + while (1) { +/*20*/ + p=p->next; + if (p==staticVars2.target) { // alle durch + // printit! + if (p->owner->buffer) { + +/* + * SS: now we should remove the mouse pointer from the screen. This is + * not necessary because we have a copy of the screen. + * + * if (p->owner->buffer == TScreen::screenBuffer) TScreen::drawMouse(0); + */ + + if (shadowCounter == 0) + { + /* SS: writes a row of data to the screen */ + + if (p->owner->buffer == TScreen::screenBuffer) + TScreen::writeRow( + p->owner->size.x * staticVars2.y + x1, + staticVars1.buf + (x1 - staticVars2.offset), + x2 - x1); + memmove(p->owner->buffer + p->owner->size.x * staticVars2.y + + x1, staticVars1.buf + x1 - staticVars2.offset, + (x2 - x1) * 2); + } else { // paint with shadowAttr + int l = x2 - x1; + int dst1 = p->owner->size.x * staticVars2.y + x1; + ushort *dst = p->owner->buffer + dst1; + ushort *src= staticVars1.buf + (x1 - staticVars2.offset); + while (l--) + { + ushort d = *src++ & 0xff | (shadowAttr << 8); + + /* SS: writes a character on the screen */ + + if (p->owner->buffer == TScreen::screenBuffer) + TScreen::writeRow(dst1++, &d, 1); + *dst++ = d; + } + } + +/* SS: draws mouse pointer */ + +if (p->owner->buffer == TScreen::screenBuffer) TScreen::drawMouse(1); + }; + if (p->owner->lockFlag==0) writeViewRec2( x1, x2, p->owner, shadowCounter ); + return ; // (p->owner->lockFlag==0); + }; + if ( !(p->state & sfVisible) || staticVars2.y<p->origin.y) continue; // keine Verdeckung + + if ( staticVars2.y<p->origin.y+p->size.y ) { + // šberdeckung m”glich. + if (x1<p->origin.x) { // f„ngt links vom Object an. + if (x2<=p->origin.x) continue; // links vorbei + writeViewRec1( x1, p->origin.x, p, shadowCounter ); + x1=p->origin.x; + }; + // if (x1>=p->origin.x) { + if ( x2<=p->origin.x+p->size.x ) return; // komplett verdeckt. + if ( x1<p->origin.x+p->size.x ) x1=p->origin.x+p->size.x; + // if ( x1>=p->origin.x+p->size.x ) { // k”nnte h”chstens im Schatten liegen + if ( (p->state & sfShadow) && (staticVars2.y>=p->origin.y+shadowSize.y)) { + if (x1>=p->origin.x+p->size.x+shadowSize.x) { + continue; // rechts vorbei + } else { + shadowCounter++; + if (x2<=p->origin.x+p->size.x+shadowSize.x) { + continue; // alles im Schatten + } else { // aufteilen Schattenteil, rechts daneben + writeViewRec1( x1, p->origin.x+p->size.x+shadowSize.x, p, shadowCounter ); + x1=p->origin.x+p->size.x+shadowSize.x; + shadowCounter--; + continue; + }; + }; + } else { + continue; // rechts vorbei, 1.Zeile hat keinen Schatten + }; + }; + if ( (p->state & sfShadow) && (staticVars2.y < p->origin.y+p->size.y+shadowSize.y) ) { + // im y-Schatten von Object? + if (x1<p->origin.x+shadowSize.x) { + if (x2<= p->origin.x+shadowSize.x) continue; // links vorbei + writeViewRec1( x1, p->origin.x+shadowSize.x, p, shadowCounter ); + x1 = p->origin.x+shadowSize.x; + }; + if (x1>=p->origin.x+shadowSize.x+p->size.x) continue; + shadowCounter++; + if (x2<=p->origin.x+p->size.x+shadowSize.x) { + continue; // alles im Schatten + } else { // aufteilen Schattenteil, rechts daneben + writeViewRec1( x1, p->origin.x+p->size.x+shadowSize.x, p, shadowCounter ); + x1=p->origin.x+p->size.x+shadowSize.x; + shadowCounter--; + continue; + }; + + } else { // zu weit unten + continue; + }; + + }; // while + +} + +void TView::writeViewRec2( short x1, short x2, TView* p, int shadowCounter ) { + if (!(p->state & sfVisible) || p->owner==0 ) return; + + StaticVars2 savedStatics = staticVars2; + + staticVars2.y += p->origin.y; + x1 += p->origin.x; + x2 += p->origin.x; + staticVars2.offset += p->origin.x; + staticVars2.target=p; + + TGroup* g=p->owner; + if (staticVars2.y<g->clip.a.y || staticVars2.y >= g->clip.b.y) { + staticVars2 = savedStatics; + return; + }; + if (x1<g->clip.a.x) x1 = g->clip.a.x; + if (x2>g->clip.b.x) x2 = g->clip.b.x; + if (x1>=x2) { + staticVars2 = savedStatics; + return; + }; + + writeViewRec1( x1, x2, g->last, shadowCounter ); + staticVars2 = savedStatics; +} + +void TView::writeView( short x1, short x2, short y, const void* buf ) { +// cerr << "Output "; + if (y<0 || y>=size.y) return; + if (x1<0) x1=0; + if (x2>size.x) x2=size.x; + if (x1>=x2) return; + staticVars2.offset=x1; + staticVars1.buf= (ushort*) buf; + staticVars2.y=y; + writeViewRec2( x1, x2, this, 0 ); + doRefresh(this); +} + +void TView::writeBuf( short x, short y, short w, short h, const void *buf) { + lockRefresh++; /* stop the refresh */ + for (int i=0; i<h; i++) { + writeView( x,x+w,y+i,(ushort*) buf + w*i ); + } /* endfor */ + lockRefresh--; /* allow the refresh */ + doRefresh(this); +} + +void TView::writeChar( short x, short y, char c, uchar color, short count) { + ushort b[maxViewWidth]; + ushort myChar= ( ((ushort)mapColor(color))<<8 ) + (unsigned char) c; + short count2=count; + if (x<0) x=0; + if (x+count>maxViewWidth) return; + ushort* p = b; + while ( count-- ) *p++ = myChar; + writeView( x, x+count2, y, b); +} + +void TView::writeLine( short x, short y, short w, short h, const void *buf) { + if (h==0) return; + lockRefresh++; /* stop the refresh */ + for (int i=0; i<h; i++) { + writeView ( x, x+w, y+i, buf ); + }; + lockRefresh--; /* allow the refresh */ + doRefresh(this); +} + +void TView::writeStr( short x, short y, const char *str, uchar color) { + if (!str) return; + ushort l= strlen(str); + if (l==0) return; + if (l>maxViewWidth) l=maxViewWidth; + ushort l2=l; + ushort myColor=( (ushort)mapColor(color) ) << 8; + ushort b[maxViewWidth]; + ushort* p = b; + while ( *p++ = myColor+(*(const unsigned char*)str++), --l ); + writeView ( x, x+l2, y, b ); +} |