home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
pub
/
win100b
/
wktsmt.c
< prev
next >
Wrap
C/C++ Source or Header
|
2020-01-01
|
36KB
|
1,434 lines
/*
* Smart terminal module
*
* Copyright (c) 1990, 1991 by
* William S. Hall
* 3665 Benton Street #66
* Santa Clara, CA 95051
*
*/
#define NOSOUND
#define NOCOMM
#define NOKANJI
#define NOATOM
#include <windows.h>
#if defined(WIN2)
#define SYMBOL_CHARSET 2
#include <winexp.h>
#endif
#include <string.h>
#include <ascii.h>
#ifdef COLUMBIA
#include "wktsmt.h"
#else
#include "smterm.h"
#endif
static void NEAR TermWndPaint(PSMT pSmt, LPPAINTSTRUCT lpps);
static int NEAR SmartTermDisplay(PSMT pSmt, BYTE *str, short len);
static void NEAR ComputeVisibleWindow(PSMT pSmt, short right, short bottom);
static void NEAR DoCR(PSMT pSmt);
static void NEAR DoLF(PSMT pSmt);
static void NEAR DoBS(PSMT pSmt);
static void NEAR AdjustWindowToCursor(PSMT pSmt);
static void NEAR CursorUp(PSMT pSmt, int count);
static void NEAR CursorDown(PSMT pSmt, int count);
static void NEAR CursorRight(PSMT pSmt, int count);
static void NEAR CursorLeft(PSMT pSmt, int count);
static void NEAR ClearToEndOfLine(PSMT pSmt);
static void NEAR ClearToEndOfPage(PSMT pSmt);
static void NEAR PositionCursor(PSMT pSmt, short r, short c);
static void NEAR ReverseIndex(PSMT pSmt);
static void NEAR DoHT(PSMT pSmt);
static void NEAR AlignScreen(PSMT pSmt);
static void NEAR ClearScreen(PSMT pSmt);
static void NEAR SaveCursor(PSMT pSmt, BOOL flag);
static void NEAR ClearToTopOfPage(PSMT pSmt);
static void NEAR ClearToLineStart(PSMT pSmt);
static void NEAR ClearLine(PSMT pSmt);
static void NEAR ShowLineOfText(PSMT pSmt, HDC hDC, BYTE *str, short len,
short xpos, short ypos, BYTE attrib);
static void NEAR InsertLine(PSMT pSmt, int count);
static void NEAR DeleteLine(PSMT pSmt, int count);
static void NEAR DeleteChar(PSMT pSmt, WORD count);
static void NEAR SetTabStop(PSMT pSmt, LONG param);
static void NEAR ChangeColors(PSMT pSmt, LONG *pColors);
static void NEAR SetVideoAttrib(PSMT pSmt, WORD index);
static void NEAR SetScrollRegion(PSMT pSmt, int top, int bottom);
static void NEAR FillScreen(PSMT pSmt);
static void NEAR SetScreen(PSMT pSmt, WORD rows, WORD cols);
static long NEAR CalcScrollRange(PSMT pSmt, short xsize, short ysize);
static void NEAR CopyLines(PSMT pSmt, short start, short end, LPSTR pbuf);
static void NEAR FlipScreen(PSMT pSmt, short top, short bottom);
static void NEAR SetCharSet(PSMT pSmt, WORD index);
static void NEAR wordmemset(WORD *dest, WORD val, int count);
static void NEAR scrollindex(PSMT pSmt, BOOL direction);
static void NEAR SetOriginMode(PSMT pSmt, BOOL param);
static void NEAR SmartTermCommand(register PSMT pSmt,
register WORD wParam, LONG lParam);
static void NEAR SetFont(PSMT pSmt, SETFONT FAR *lplf);
static void NEAR ScrollBack(PSMT pSmt, int lines, BOOL direction);
long FAR PASCAL SmartTermWndProc(HWND hWnd, unsigned message,
WORD wParam, LONG lParam)
{
register PSMT pSmt = (PSMT)GetWindowWord(hWnd,0);
PAINTSTRUCT ps;
long numrem;
switch(message) {
case SMT_STRINGINPUT:
HideCaret(hWnd);
numrem = SmartTermDisplay(pSmt,(BYTE *)LOWORD(lParam),(short)wParam);
SetCaretPos(pSmt->Pos.x, pSmt->Pos.y + pSmt->CharHeight);
ShowCaret(hWnd);
return ((LONG)numrem);
break;
case SMT_COMMAND:
HideCaret(hWnd);
SmartTermCommand(pSmt, wParam, lParam);
SetCaretPos(pSmt->Pos.x, pSmt->Pos.y + pSmt->CharHeight);
ShowCaret(hWnd);
break;
case SMT_SIZEPARENT:
ComputeVisibleWindow(pSmt, LOWORD(lParam), HIWORD(lParam));
MoveWindow(pSmt->hStatic, pSmt->vrect.left,
pSmt->vrect.top,
pSmt->vrect.right,
pSmt->vrect.bottom, TRUE);
pSmt->rect.left = pSmt->rect.top = 0;
MoveWindow(pSmt->hWnd,pSmt->rect.left, pSmt->rect.top,
pSmt->rect.right, pSmt->rect.bottom,TRUE);
AdjustWindowToCursor(pSmt);
return(CalcScrollRange(pSmt,(short)LOWORD(lParam),
(short)HIWORD(lParam)));
break;
case SMT_CARETFUNCTION:
switch(wParam) {
case SM_CREATECARET:
if (HIWORD(lParam))
CreateCaret(pSmt->hWnd,(HBITMAP)NULL,
pSmt->CharWidth,-pSmt->CharHeight);
else
CreateCaret(pSmt->hWnd,(HBITMAP)NULL,
pSmt->CharWidth,-2);
SetCaretPos(pSmt->Pos.x, pSmt->Pos.y + pSmt->CharHeight);
if (LOWORD(lParam))
ShowCaret(pSmt->hWnd);
break;
case SM_DESTROYCARET:
HideCaret(pSmt->hWnd);
DestroyCaret();
break;
case SM_HIDECARET:
HideCaret(pSmt->hWnd);
break;
case SM_SHOWCARET:
ShowCaret(pSmt->hWnd);
break;
case SM_GETCARETPOS:
return(MAKELONG(1 + pSmt->Pos.y / pSmt->CharHeight,
pSmt->CurLineOffset + 1));
}
break;
case SMT_SETATTRIBUTE:
switch(wParam) {
case SM_COLORCHANGE:
ChangeColors(pSmt, (LONG *)LOWORD(lParam));
break;
case SM_AUTOWRAP:
pSmt->Wrap = LOWORD(lParam);
break;
case SM_MARGINBELL:
pSmt->MarginBell = LOWORD(lParam);
break;
case SM_SMOOTHSCROLL:
pSmt->SmoothScroll = LOWORD(lParam);
break;
case SM_INSERT:
pSmt->ICToggle = LOWORD(lParam);
break;
case SM_SCROLLUNITS:
pSmt->ScrollUnits = LOWORD(lParam);
break;
}
break;
case SMT_GETATTRIBUTE:
switch(wParam) {
case SM_AUTOWRAP:
return((LONG)pSmt->Wrap);
break;
case SM_MARGINBELL:
return((LONG)pSmt->MarginBell);
break;
case SM_SMOOTHSCROLL:
return((LONG)pSmt->SmoothScroll);
break;
case SM_SCREENSIZE:
return(MAKELONG(pSmt->MaxLines, pSmt->MaxCols));
break;
case SM_FONTFACE:
lstrcpy((LPSTR)lParam, pSmt->lfnt.lfFaceName);
return lstrlen(pSmt->lfnt.lfFaceName);
case SM_NORMALFONT:
return MAKELONG(pSmt->NFontWidth, pSmt->NFontHeight);
case SM_SMALLFONT:
return MAKELONG(pSmt->SFontWidth, pSmt->SFontHeight);
case SM_SCROLLUNITS:
return (LONG)pSmt->ScrollUnits;
}
break;
case SMT_SHOWWINDOW:
ShowWindow(pSmt->hStatic, wParam);
break;
case SMT_INVERT:
FlipScreen(pSmt, LOWORD(lParam), HIWORD(lParam));
break;
case SMT_COPYLINES:
CopyLines(pSmt, (int)LOBYTE(wParam), (int)HIBYTE(wParam),
(LPSTR)lParam);
break;
case WM_CREATE:
SmartTermWndCreate(hWnd, lParam);
break;
case WM_PAINT:
BeginPaint(hWnd, (LPPAINTSTRUCT)&ps);
TermWndPaint(pSmt, (LPPAINTSTRUCT)&ps);
EndPaint(hWnd, (LPPAINTSTRUCT)&ps);
break;
case WM_ERASEBKGND:
SelectObject((HDC)wParam, pSmt->hbr);
FillRect((HDC)wParam, (LPRECT)&pSmt->rect, pSmt->hbr);
return (LONG)TRUE;
case WM_DESTROY:
if (pSmt->hbr)
DeleteObject(pSmt->hbr);
if (pSmt->hFont)
DeleteObject(pSmt->hFont);
break;
default:
return ((long)DefWindowProc(hWnd,message,wParam,lParam));
break;
}
return(0L);
}
static void NEAR SmartTermCommand(register PSMT pSmt,
register WORD wParam, LONG lParam)
{
switch(wParam) {
case SM_CURSORHOME:
pSmt->HaveToWrap = FALSE;
PositionCursor(pSmt, 0, 0);
break;
case SM_CURSORUP:
CursorUp(pSmt, LOWORD(lParam));
break;
case SM_CURSORDOWN:
CursorDown(pSmt, LOWORD(lParam));
break;
case SM_CURSORRIGHT:
CursorRight(pSmt, LOWORD(lParam));
break;
case SM_CURSORLEFT:
CursorLeft(pSmt, LOWORD(lParam));
break;
case SM_CLRTOENDOFLINE:
ClearToEndOfLine(pSmt);
break;
case SM_CLRTOENDOFPAGE:
ClearToEndOfLine(pSmt);
ClearToEndOfPage(pSmt);
break;
case SM_POSITIONCURSOR:
pSmt->HaveToWrap = FALSE;
PositionCursor(pSmt,(short)LOWORD(lParam) - 1,
(short)HIWORD(lParam) - 1);
break;
case SM_REVERSEINDEX:
while (lParam--)
ReverseIndex(pSmt);
break;
case SM_INDEX:
while (lParam--)
DoLF(pSmt);
break;
case SM_NEXTLINE:
while (lParam--) {
DoCR(pSmt);
DoLF(pSmt);
}
break;
case SM_ALIGNSCREEN:
AlignScreen(pSmt);
break;
case SM_SAVECURSOR:
SaveCursor(pSmt, LOWORD(lParam));
break;
case SM_CLEARSCREEN:
ClearScreen(pSmt);
break;
case SM_CLEARTOTOPOFPAGE:
ClearToTopOfPage(pSmt);
ClearToLineStart(pSmt);
break;
case SM_CLEARTOLINESTART:
ClearToLineStart(pSmt);
break;
case SM_CLEARLINE:
ClearLine(pSmt);
break;
case SM_DELETECHAR:
DeleteChar(pSmt, LOWORD(lParam));
break;
case SM_INSERTLINE:
InsertLine(pSmt, LOWORD(lParam));
break;
case SM_DELETELINE:
DeleteLine(pSmt, LOWORD(lParam));
break;
case SM_SETTAB:
SetTabStop(pSmt, lParam);
break;
case SM_VIDEOATTRIB:
SetVideoAttrib(pSmt, LOWORD(lParam));
break;
case SM_SCROLLREGION:
SetScrollRegion(pSmt, LOWORD(lParam), HIWORD(lParam));
break;
case SM_FILLSCREEN:
FillScreen(pSmt);
break;
case SM_HSCROLL:
pSmt->rect.left = -LOWORD(lParam) * pSmt->CharWidth;
MoveWindow(pSmt->hWnd, pSmt->rect.left, pSmt->rect.top,
pSmt->rect.right, pSmt->rect.bottom, TRUE);
break;
case SM_SETCOLS:
SetScreen(pSmt, pSmt->MaxLines, LOWORD(lParam));
break;
case SM_LEFTMARGIN:
while (lParam--)
DoCR(pSmt);
break;
case SM_TAB:
while (lParam--)
DoHT(pSmt);
break;
case SM_BKSP:
while (lParam--)
DoBS(pSmt);
break;
case SM_SETCHARSET:
SetCharSet(pSmt, LOWORD(lParam));
break;
case SM_ORIGINMODE:
SetOriginMode(pSmt, LOWORD(lParam));
break;
case SM_SETFONT:
SetFont(pSmt, (SETFONT FAR *)lParam);
break;
case SM_SCROLLBACK:
ScrollBack(pSmt, LOWORD(lParam), (BOOL)HIWORD(lParam));
break;
case SM_PAGEBACK:
ScrollBack(pSmt, pSmt->MaxLines, (BOOL)HIWORD(lParam));
break;
case SM_HOMEEND:
ScrollBack(pSmt, pSmt->MaxTextLines, (BOOL)HIWORD(lParam));
break;
}
}
static void NEAR ScrollBack(PSMT pSmt, int numlines, BOOL direction)
{
register int buflines = pSmt->MaxTextLines;
WORD *temp;
register int i;
if (direction) {
numlines = min(numlines, pSmt->scrollback);
if (numlines > 0) {
for (i = 0; i < numlines; i++) {
temp = pSmt->lines[buflines - 1];
memmove(&pSmt->lines[1],
&pSmt->lines[0],
(buflines - 1) * sizeof(WORD *));
pSmt->lines[0] = temp;
}
pSmt->scrollback -= numlines;
pSmt->scrollforward += numlines;
ScrollWindow(pSmt->hWnd,0,numlines * pSmt->CharHeight,
NULL,&pSmt->srect);
UpdateWindow(pSmt->hWnd);
}
}
else {
numlines = min(numlines, pSmt->scrollforward);
if (numlines > 0) {
for (i = 0; i < numlines; i++) {
temp = pSmt->lines[0];
memmove(&pSmt->lines[0],
&pSmt->lines[1],
(buflines - 1) * sizeof(WORD *));
pSmt->lines[buflines - 1] = temp;
}
pSmt->scrollback += numlines;
pSmt->scrollforward -= numlines;
ScrollWindow(pSmt->hWnd, 0, -numlines * pSmt->CharHeight,
NULL, &pSmt->srect);
UpdateWindow(pSmt->hWnd);
}
}
}
static void NEAR SetFont(PSMT pSmt, SETFONT FAR *lpsf)
{
RECT size;
pSmt->NFontWidth = lpsf->nwidth;
pSmt->NFontHeight = lpsf->nheight;
pSmt->SFontWidth = lpsf->swidth;
pSmt->SFontHeight = lpsf->sheight;
lstrcpy(pSmt->lfnt.lfFaceName, lpsf->FaceName);
pSmt->hFont = SetFontData(pSmt);
pSmt->srect.right = pSmt->rect.right = pSmt->CharWidth * pSmt->MaxCols;
pSmt->srect.bottom = pSmt->rect.bottom = pSmt->CharHeight * pSmt->MaxLines;
PositionCursor(pSmt, pSmt->CurLine, pSmt->CurLineOffset);
GetClientRect(pSmt->hMain, &size);
PostMessage(pSmt->hMain, WM_SIZE, SIZENORMAL,
MAKELONG(size.right, size.bottom));
}
static void NEAR SetCharSet(PSMT pSmt, WORD index)
{
register BYTE hattrib = (BYTE)HIBYTE((int)pSmt->Attrib);
if (index)
hattrib |= VA_SPECIAL;
else
hattrib &= ~VA_SPECIAL;
pSmt->Attrib = 256 * hattrib;
}
/* character deletion */
static void NEAR DeleteChar(PSMT pSmt, WORD count)
{
RECT rect;
short offset = pSmt->CurLineOffset;
WORD *dest = pSmt->lines[pSmt->CurLine] + offset;
register short copycount;
register WORD maxdelchars;
if (count > (maxdelchars = pSmt->MaxCols - offset))
count = maxdelchars;
copycount = maxdelchars - count;
memmove((BYTE *)dest, (BYTE *)(dest + count), copycount * sizeof (WORD));
wordmemset(dest + copycount, SP, count);
SetRect(&rect, pSmt->Pos.x, pSmt->Pos.y,
pSmt->rect.right, pSmt->Pos.y + pSmt->CharHeight);
ScrollWindow(pSmt->hWnd,-pSmt->CharWidth * count, 0, &rect, &rect);
UpdateWindow(pSmt->hWnd);
}
static void NEAR FlipScreen(PSMT pSmt, short top, short bottom)
{
register int i, j;
WORD mask = 256 * VA_MARK;
short cols = pSmt->MaxCols;
RECT rect;
if ((top < 0) || (bottom > pSmt->MaxLines))
return;
for (i = top; i <= bottom; i++)
for (j = 0; j < cols; j++)
*(pSmt->lines[i] + j) ^= mask;
rect.left = 0;
rect.right = pSmt->rect.right;
rect.top = top * pSmt->CharHeight;
rect.bottom = (bottom + 1) * pSmt->CharHeight;
InvalidateRect(pSmt->hWnd, &rect, FALSE);
}
static void NEAR CopyLines(PSMT pSmt, short start, short end, LPSTR pbuf)
{
register int i, j;
short cols = pSmt->MaxCols;
int count;
for (i = start; i <= end; i++) {
for (j = cols - 1; (j >= 0) && (LOBYTE(*(pSmt->lines[i] + j)) == SP); j--)
;
count = j + 1;
for (j = 0; j < count; j++)
*pbuf++ = LOBYTE(*(pSmt->lines[i] + j));
*pbuf++ = '\r';
*pbuf++ = '\n';
}
}
static long NEAR CalcScrollRange(PSMT pSmt, short xsize, short ysize)
{
register short xrange, yrange;
short diff;
diff = pSmt->rect.right - xsize;
if (diff > 0) {
xrange = diff / pSmt->CharWidth;
if (diff % pSmt->CharWidth)
xrange += 1;
}
else
xrange = 0;
yrange = pSmt->rect.bottom - ysize;
yrange = (yrange > 0 ? (yrange / pSmt->CharHeight) : 0);
return MAKELONG(xrange, yrange);
}
static void NEAR SetScreen(PSMT pSmt, WORD rows, WORD cols)
{
short size = rows * cols;
HFONT hfont, holdfont;
HDC hDC;
TEXTMETRIC TM;
register int i,j;
if (cols == MAXCOLUMNS) {
pSmt->lfnt.lfWidth = pSmt->SFontWidth;
pSmt->lfnt.lfHeight = pSmt->SFontHeight;
pSmt->Bold = pSmt->SBold;
pSmt->Symbol = pSmt->SSymbol;
}
else {
pSmt->lfnt.lfWidth = pSmt->NFontWidth;
pSmt->lfnt.lfHeight = pSmt->NFontHeight;
pSmt->Bold = pSmt->NBold;
pSmt->Symbol = pSmt->NSymbol;
}
hDC = GetDC(pSmt->hWnd);
hfont = CreateFontIndirect(&pSmt->lfnt);
holdfont = SelectObject(hDC, hfont);
GetTextMetrics(hDC, &TM);
pSmt->CharHeight = TM.tmHeight + TM.tmExternalLeading;
pSmt->CharWidth = TM.tmAveCharWidth;
SelectObject(hDC, holdfont);
ReleaseDC(pSmt->hWnd, hDC);
if (pSmt->hFont)
DeleteObject(pSmt->hFont);
pSmt->hFont = hfont;
pSmt->MaxCols = cols;
pSmt->MaxLines = rows;
for (i = 0; i < MAXTEXTBUFFERS * pSmt->MaxLines; i++) {
pSmt->lines[i] = (pSmt->pVidBuffer + i * MAXCOLUMNS);
for (j = 0; j < MAXCOLUMNS; j++)
*(pSmt->lines[i] + j) = SP;
}
pSmt->scrollback = 0;
pSmt->scrollforward = 0;
pSmt->TopScroll = pSmt->TopOrgLine = 0;
pSmt->BottomScroll = pSmt->BottomOrgLine = pSmt->MaxLines - 1;
pSmt->CurLine = 0;
pSmt->CurLineOffset = 0;
pSmt->Pos.x = pSmt->Pos.y = 0;
pSmt->rect.left = pSmt->rect.top = 0;
pSmt->srect.right = pSmt->rect.right = pSmt->CharWidth * pSmt->MaxCols;
pSmt->srect.bottom = pSmt->rect.bottom = pSmt->CharHeight * pSmt->MaxLines;
InvalidateRect(pSmt->hWnd, (LPRECT)NULL, TRUE);
}
static void NEAR SetVideoAttrib(PSMT pSmt, WORD index)
{
register BYTE hattrib = (BYTE)HIBYTE((int)pSmt->Attrib);
register BYTE special = (BYTE)(hattrib & VA_SPECIAL);
switch(index) {
case 0:
hattrib = (BYTE)(VA_NORMAL | special);
break;
case 1:
hattrib |= VA_BOLD;
break;
case 4:
hattrib |= VA_UNDERLINE;
break;
case 5:
hattrib |= VA_BLINK;
break;
case 7:
hattrib |= VA_REVERSE;
break;
case 8:
hattrib |= VA_DIM;
break;
case 22:
hattrib &= ~VA_BOLD;
break;
case 24:
hattrib &= ~VA_UNDERLINE;
break;
case 25:
hattrib &= ~VA_BLINK;
break;
case 27:
hattrib &= ~VA_REVERSE;
break;
case 28:
hattrib &= ~VA_DIM;
break;
}
pSmt->Attrib = 256 * hattrib;
}
static void NEAR SetScrollRegion(PSMT pSmt, int top, int bottom)
{
register short max = pSmt->MaxLines;
register short cheight = pSmt->CharHeight;
if ((top <= max) && (bottom <= max)) {
if (top == 0)
top = 1;
if (bottom == 0)
bottom = max;
if (top < bottom) {
pSmt->srect.top = cheight * (top - 1);
pSmt->srect.bottom = cheight * bottom;
pSmt->TopScroll = top - 1;
pSmt->BottomScroll = bottom - 1;
if (pSmt->OriginMode)
SetOriginMode(pSmt, TRUE);
else
PositionCursor(pSmt, 0, 0);
}
}
}
static void NEAR ChangeColors(register PSMT pSmt, LONG *pColors)
{
pSmt->TextColor = pColors[0];
pSmt->BGColor = pColors[1];
DeleteObject(pSmt->hbr);
pSmt->hbr = CreateSolidBrush(pSmt->BGColor);
InvalidateRect(pSmt->hWnd, (LPRECT)NULL, TRUE);
}
static void NEAR InsertLine(register PSMT pSmt, int count)
{
register int i;
WORD *save[MAXROWS];
RECT rect;
short top = pSmt->TopScroll;
short cur = pSmt->CurLine;
short bottom = pSmt->BottomScroll;
short len;
if ((top <= cur) && (cur <= bottom)) {
count = min(bottom - cur + 1, count);
len = bottom - count + 1;
for (i = 0; i < count; i++)
save[cur + i] = pSmt->lines[len + i];
for (i = bottom; i >= cur + count; i--)
pSmt->lines[i] = pSmt->lines[i - count];
for (i = cur; i < cur + count; i++) {
pSmt->lines[i] = save[i];
wordmemset(pSmt->lines[i], SP, pSmt->MaxCols);
}
DoCR(pSmt);
SetRect(&rect, 0, pSmt->Pos.y, pSmt->srect.right, pSmt->srect.bottom);
ScrollWindow(pSmt->hWnd, 0, count * pSmt->CharHeight, &rect, &rect);
UpdateWindow(pSmt->hWnd);
}
}
static void NEAR DeleteLine(PSMT pSmt, int count)
{
register int i;
WORD *save[MAXROWS];
RECT rect;
short top = pSmt->TopScroll;
short cur = pSmt->CurLine;
short bottom = pSmt->BottomScroll;
short len;
if ((top <= cur) && (cur <= bottom)) {
count = min(bottom - cur + 1, count);
len = bottom - count + 1;
for (i = 0; i < count; i++)
save[len + i] = pSmt->lines[cur + i];
for (i = cur + count; i <= bottom; i++)
pSmt->lines[i - count] = pSmt->lines[i];
for (i = len; i <= bottom; i++) {
pSmt->lines[i] = save[i];
wordmemset(pSmt->lines[i], SP, pSmt->MaxCols);
}
DoCR(pSmt);
SetRect(&rect, 0, pSmt->Pos.y, pSmt->srect.right, pSmt->srect.bottom);
ScrollWindow(pSmt->hWnd, 0, -count * pSmt->CharHeight, &rect, &rect);
UpdateWindow(pSmt->hWnd);
}
}
static void NEAR SaveCursor(PSMT pSmt, BOOL flag)
{
if (flag) {
pSmt->CurSaveX = pSmt->CurLineOffset;
pSmt->CurSaveY = pSmt->CurLine;
pSmt->SaveAttrib = pSmt->Attrib;
// pSmt->SaveCharSet = lfnt.lfCharSet;
}
else {
PositionCursor(pSmt, pSmt->CurSaveY, pSmt->CurSaveX);
pSmt->Attrib = pSmt->SaveAttrib;
// lfnt.lfCharSet = pSmt->SaveCharSet;
}
}
static void NEAR SetTabStop(PSMT pSmt, LONG param)
{
register BOOL set = LOWORD(param);
register WORD val = HIWORD(param);
if (set)
pSmt->TabStops[pSmt->CurLineOffset] = 'T';
else {
if (val == 3)
memset(pSmt->TabStops, SP, MAXCOLUMNS);
else if (val == 0)
pSmt->TabStops[pSmt->CurLineOffset] = SP;
}
}
static void NEAR ClearToEndOfLine(PSMT pSmt)
{
RECT rect;
register short offset = pSmt->CurLineOffset;
register short ypos = pSmt->Pos.y;
wordmemset(pSmt->lines[pSmt->CurLine] + offset,SP,pSmt->MaxCols - offset);
SetRect(&rect,pSmt->Pos.x,ypos,pSmt->rect.right,ypos + pSmt->CharHeight);
InvalidateRect(pSmt->hWnd, (LPRECT)&rect, TRUE);
UpdateWindow(pSmt->hWnd);
}
static void NEAR ClearToLineStart(PSMT pSmt)
{
RECT rect;
register short offset = pSmt->CurLineOffset+ 1;
register short width = offset * pSmt->CharWidth;
wordmemset(pSmt->lines[pSmt->CurLine], SP, offset);
SetRect(&rect, 0, pSmt->Pos.y, width, pSmt->Pos.y + pSmt->CharHeight);
InvalidateRect(pSmt->hWnd, (LPRECT)&rect, TRUE);
UpdateWindow(pSmt->hWnd);
}
static void NEAR ClearLine(PSMT pSmt)
{
RECT rect;
wordmemset(pSmt->lines[pSmt->CurLine], SP, pSmt->MaxCols);
SetRect((LPRECT)&rect, 0, pSmt->Pos.y, pSmt->rect.right,
pSmt->Pos.y + pSmt->CharHeight);
InvalidateRect(pSmt->hWnd, (LPRECT)&rect, TRUE);
UpdateWindow(pSmt->hWnd);
}
static void NEAR ClearToEndOfPage(PSMT pSmt)
{
RECT rect;
register int i;
for (i = pSmt->CurLine; i < pSmt->MaxLines; i++)
wordmemset(pSmt->lines[i], SP, pSmt->MaxCols);
SetRect(&rect, 0, pSmt->Pos.y + pSmt->CharHeight,
pSmt->rect.right, pSmt->rect.bottom);
InvalidateRect(pSmt->hWnd, &rect, TRUE);
UpdateWindow(pSmt->hWnd);
}
static void NEAR ClearToTopOfPage(PSMT pSmt)
{
RECT rect;
register int i;
for (i = 0; i < pSmt->CurLine; i++)
wordmemset(pSmt->lines[i], SP, pSmt->MaxCols);
SetRect(&rect, 0, 0, pSmt->rect.right, pSmt->Pos.y);
InvalidateRect(pSmt->hWnd, &rect, TRUE);
UpdateWindow(pSmt->hWnd);
}
static void NEAR ClearScreen(PSMT pSmt)
{
register int i;
for (i = 0; i < pSmt->MaxLines; i++)
wordmemset(pSmt->lines[i], SP, pSmt->MaxCols);
InvalidateRect(pSmt->hWnd, NULL, TRUE);
UpdateWindow(pSmt->hWnd);
}
static void NEAR AlignScreen(PSMT pSmt)
{
register int i;
for (i = 0; i < pSmt->MaxLines; i++)
wordmemset(pSmt->lines[i], 'E', pSmt->MaxCols);
InvalidateRect(pSmt->hWnd, NULL, TRUE);
UpdateWindow(pSmt->hWnd);
PositionCursor(pSmt, 0, 0);
}
static void NEAR FillScreen(PSMT pSmt)
{
register int i,j;
BYTE ch = 0;
for (i = 0; i < pSmt->MaxLines; i++)
for (j = 0; j < pSmt->MaxCols; j++)
*(pSmt->lines[i] + j) = (WORD)ch++;
InvalidateRect(pSmt->hWnd, NULL, TRUE);
UpdateWindow(pSmt->hWnd);
PositionCursor(pSmt, 0, 0);
}
static void NEAR SetOriginMode(PSMT pSmt, BOOL param)
{
if (param) {
pSmt->TopOrgLine = pSmt->TopScroll;
pSmt->BottomOrgLine = pSmt->BottomScroll;
}
else {
pSmt->TopOrgLine = 0;
pSmt->BottomOrgLine = (pSmt->MaxLines - 1);
}
pSmt->OriginMode = param;
PositionCursor(pSmt, 0, 0);
}
static void NEAR PositionCursor(PSMT pSmt, short r, short c)
{
register short rows = pSmt->BottomOrgLine;
register short cols = pSmt->MaxCols;
if (c >= cols)
c = cols - 1 ;
pSmt->Pos.x = c * pSmt->CharWidth;
pSmt->CurLineOffset = c;
r += pSmt->TopOrgLine;
if (r > rows)
r = rows;
pSmt->Pos.y = r * pSmt->CharHeight;
pSmt->CurLine = r;
AdjustWindowToCursor(pSmt);
}
static int NEAR SmartTermDisplay(PSMT pSmt, BYTE *str, short len)
{
register BYTE *ptr;
register short ctr;
short cols = pSmt->MaxCols;
short cwidth = pSmt->CharWidth;
short width = pSmt->rect.right;
short txpos;
short toff;
WORD *tBuf;
WORD attrib = pSmt->Attrib;
WORD savebuf[MAXCOLUMNS];
while (len > 0) {
ptr = str;
ctr = 0;
toff = pSmt->CurLineOffset;
if (pSmt->HaveToWrap && pSmt->Wrap && (toff == (cols - 1))) {
DoCR(pSmt);
DoLF(pSmt);
toff = pSmt->CurLineOffset;
pSmt->HaveToWrap = FALSE;
}
txpos = pSmt->Pos.x;
tBuf = pSmt->lines[pSmt->CurLine];
while ((len > 0) && (toff < cols)) {
if (pSmt->ICToggle)
savebuf[ctr] = *(tBuf + toff);
*(tBuf + toff++) = *ptr++ + attrib;
if ((pSmt->MarginBell) && (toff == (cols - 8)))
MessageBeep(0);
ctr += 1;
txpos += cwidth;
len -= 1;
}
if (ctr) {
if (pSmt->ICToggle) {
RECT rect;
short ypos = pSmt->Pos.y;
short xpos = pSmt->Pos.x;
short tomove, tocopy;
tomove = cols - toff - ctr;
tocopy = min (ctr, cols - toff);
if (tomove > 0)
memmove(tBuf + toff + ctr, tBuf + toff, tomove);
if (tocopy > 0)
strncpy((BYTE *)(tBuf + toff),
(BYTE *)savebuf, sizeof(WORD) * tocopy);
SetRect(&rect, xpos, ypos, width, ypos + pSmt->CharHeight);
ScrollWindow(pSmt->hWnd, txpos - xpos, 0, &rect, &rect);
UpdateWindow(pSmt->hWnd);
}
else {
HDC hDC = GetDC(pSmt->hWnd);
ShowLineOfText(pSmt,hDC,str,ctr,pSmt->Pos.x,pSmt->Pos.y,
(BYTE)HIBYTE(attrib));
ReleaseDC(pSmt->hWnd, hDC);
}
if (toff < cols) {
pSmt->Pos.x = txpos;
pSmt->CurLineOffset = toff;
pSmt->HaveToWrap = FALSE;
}
else {
pSmt->CurLineOffset = (cols - 1);
pSmt->Pos.x = width - cwidth;
pSmt->HaveToWrap = TRUE;
}
}
str = ptr;
}
return (len);
}
static void NEAR ShowLineOfText(PSMT pSmt, HDC hDC, BYTE *str, short len,
short xpos, short ypos, BYTE attrib)
{
HFONT hfont, holdfont;
register BOOL underline = attrib & VA_UNDERLINE;
register BOOL bold = (attrib & VA_BOLD) && pSmt->Bold;
BOOL special = (attrib & VA_SPECIAL) && pSmt->Symbol;
if (attrib & VA_MARK) {
SetBkColor(hDC, ~pSmt->BGColor);
SetTextColor(hDC, ~pSmt->TextColor);
}
else if (attrib & VA_REVERSE) {
SetBkColor(hDC, pSmt->TextColor);
SetTextColor(hDC, pSmt->BGColor);
}
else {
SetBkColor(hDC, pSmt->BGColor);
SetTextColor(hDC, pSmt->TextColor);
}
if (bold || underline || special) {
pSmt->lfnt.lfUnderline = (BYTE)underline;
pSmt->lfnt.lfWeight = bold ? FW_BOLD : FW_NORMAL;
pSmt->lfnt.lfCharSet = (BYTE)(special ? SYMBOL_CHARSET : ANSI_CHARSET);
hfont = CreateFontIndirect(&pSmt->lfnt);
holdfont = SelectObject(hDC, hfont);
TextOut(hDC, xpos, ypos, (LPSTR)str, len);
SelectObject(hDC, holdfont);
DeleteObject(hfont);
pSmt->lfnt.lfUnderline = 0;
pSmt->lfnt.lfWeight = FW_NORMAL;
pSmt->lfnt.lfCharSet = ANSI_CHARSET;
}
else {
SelectObject(hDC, pSmt->hFont);
TextOut(hDC, xpos, ypos, (LPSTR)str, len);
}
}
static void NEAR CursorUp(PSMT pSmt, int count)
{
register short d1 = pSmt->CurLine - pSmt->TopScroll;
register short val;
if (d1) {
if (d1 > 0)
val = min(count, d1);
else
val = min(count, pSmt->CurLine);
pSmt->Pos.y -= val * pSmt->CharHeight;
pSmt->CurLine -= val;
AdjustWindowToCursor(pSmt);
}
}
static void NEAR CursorDown(PSMT pSmt, int count)
{
register short d1 = pSmt->BottomScroll - pSmt->CurLine;
register short val;
if (d1) {
if (d1 > 0)
val = min(count, d1);
else
val = min(count, pSmt->MaxLines - pSmt->CurLine - 1);
pSmt->Pos.y += val * pSmt->CharHeight;
pSmt->CurLine += val;
AdjustWindowToCursor(pSmt);
}
}
static void NEAR CursorRight(PSMT pSmt, int count)
{
register short *offset = &pSmt->CurLineOffset;
register int *xpos = &pSmt->Pos.x;
short cols = pSmt->MaxCols - 1;
short cwidth = pSmt->CharWidth;
while ((*offset < cols) && (count--)) {
*offset += 1;
*xpos += cwidth;
}
}
static void NEAR CursorLeft(PSMT pSmt, int count)
{
register short *offset = &pSmt->CurLineOffset;
register int *xpos = &pSmt->Pos.x;
short cwidth = pSmt->CharWidth;
while ((*offset > 0) && (count--)) {
*offset -= 1;
*xpos -= cwidth;
}
}
static void NEAR DoCR(PSMT pSmt)
{
pSmt->Pos.x = pSmt->CurLineOffset = 0;
}
static void NEAR DoHT(PSMT pSmt)
{
register short *offset = &pSmt->CurLineOffset;
register int *xpos;
short cwidth;
short cols = pSmt->MaxCols - 1;
if (*offset >= cols)
return;
xpos = &pSmt->Pos.x;
cwidth = pSmt->CharWidth;
do {
*offset += 1;
*xpos += cwidth;
} while ((pSmt->TabStops[*offset] != 'T') && (*offset < cols));
}
static void NEAR DoBS(PSMT pSmt)
{
if (pSmt->CurLineOffset) {
pSmt->CurLineOffset -= 1;
pSmt->Pos.x -= pSmt->CharWidth;
}
}
static void NEAR DoLF(PSMT pSmt)
{
register int scrollrem;
if (pSmt->CurLine == pSmt->BottomScroll) {
scrollindex(pSmt, TRUE);
wordmemset(pSmt->lines[pSmt->CurLine], SP, pSmt->MaxCols);
if (pSmt->SmoothScroll) {
for (scrollrem = pSmt->CharHeight;
scrollrem >= pSmt->ScrollUnits;
scrollrem -= pSmt->ScrollUnits) {
ScrollWindow(pSmt->hWnd,0,-pSmt->ScrollUnits,NULL,&pSmt->srect);
UpdateWindow(pSmt->hWnd);
}
if (scrollrem) {
ScrollWindow(pSmt->hWnd,0,-scrollrem,NULL,&pSmt->srect);
UpdateWindow(pSmt->hWnd);
}
/*
for (i = 0; i < pSmt->CharHeight/2; i++) {
ScrollWindow(pSmt->hWnd,0, -2, NULL, &pSmt->srect);
UpdateWindow(pSmt->hWnd);
}
if (pSmt->CharHeight & 1) {
ScrollWindow(pSmt->hWnd,0, -1, NULL, &pSmt->srect);
UpdateWindow(pSmt->hWnd);
}
*/
}
else {
ScrollWindow(pSmt->hWnd,0,-pSmt->CharHeight, NULL, &pSmt->srect);
UpdateWindow(pSmt->hWnd);
}
}
else if (pSmt->CurLine < (pSmt->MaxLines - 1)) {
pSmt->Pos.y += pSmt->CharHeight;
pSmt->CurLine += 1;
AdjustWindowToCursor(pSmt);
}
}
static void NEAR ReverseIndex(PSMT pSmt)
{
register int scrollrem;
if (pSmt->CurLine == pSmt->TopScroll) {
scrollindex(pSmt, FALSE);
wordmemset(pSmt->lines[pSmt->CurLine], SP, pSmt->MaxCols);
if (pSmt->SmoothScroll) {
for (scrollrem = pSmt->CharHeight;
scrollrem >= pSmt->ScrollUnits;
scrollrem -= pSmt->ScrollUnits) {
ScrollWindow(pSmt->hWnd,0,+pSmt->ScrollUnits,NULL,&pSmt->srect);
UpdateWindow(pSmt->hWnd);
}
if (scrollrem) {
ScrollWindow(pSmt->hWnd,0,+scrollrem,NULL,&pSmt->srect);
UpdateWindow(pSmt->hWnd);
}
/*
for (i = 0; i < pSmt->CharHeight/2; i++) {
ScrollWindow(pSmt->hWnd,0, 2, (LPRECT)NULL, &pSmt->srect);
UpdateWindow(pSmt->hWnd);
}
if (pSmt->CharHeight & 1) {
ScrollWindow(pSmt->hWnd, 0, 1, (LPRECT)NULL, &pSmt->srect);
UpdateWindow(pSmt->hWnd);
}
*/
}
else {
ScrollWindow(pSmt->hWnd,0, pSmt->CharHeight, NULL, &pSmt->srect);
UpdateWindow(pSmt->hWnd);
}
}
else if (pSmt->CurLine > 0) {
pSmt->Pos.y -= pSmt->CharHeight;
pSmt->CurLine -= 1;
AdjustWindowToCursor(pSmt);
}
}
static void NEAR TermWndPaint(PSMT pSmt, LPPAINTSTRUCT lpps)
{
register int i,j, k;
BYTE buf[MAXCOLUMNS];
HDC hDC = lpps->hdc;
RECT crect;
BYTE attrib;
short xpos;
short cols = pSmt->MaxCols;
short cheight = pSmt->CharHeight;
short cwidth = pSmt->CharWidth;
short count;
short leftcol = 0;
short leftbase = 0;
if (!lpps->fErase) {
SelectObject(hDC, pSmt->hbr);
FillRect(hDC, (LPRECT)&lpps->rcPaint, pSmt->hbr);
}
crect.left = lpps->rcPaint.left;
crect.right = lpps->rcPaint.right;
crect.top = 0;
crect.bottom = cheight;
/*
if (crect.left > cwidth) {
leftcol = crect.left / cwidth;
leftbase = leftcol * cwidth;
}
*/
for (j = 0; j < pSmt->MaxLines; j++) {
if (RectVisible(hDC, &crect)) {
k = 0;
xpos = leftbase;
attrib = (BYTE)HIBYTE(*pSmt->lines[j]);
for (i = cols - 1; (i >= leftcol) && (*(pSmt->lines[j] + i) == SP); i--)
;
count = i + 1;
for (i = leftcol; i < count; i++) {
if (attrib != (BYTE)HIBYTE(*(pSmt->lines[j] + i))) {
ShowLineOfText(pSmt, hDC, buf, k, xpos, crect.top, attrib);
xpos = cwidth * i;
k = 0;
attrib = (BYTE)HIBYTE(*(pSmt->lines[j] + i));
}
buf[k++] = (BYTE)LOBYTE(*(pSmt->lines[j] + i));
}
ShowLineOfText(pSmt, hDC, buf, k, xpos, crect.top, attrib);
}
crect.top += cheight;
crect.bottom += cheight;
}
}
static void NEAR scrollindex(PSMT pSmt, BOOL direction)
{
register WORD *temp;
int bottom;
register int count = pSmt->BottomScroll - pSmt->TopScroll;
if (direction) {
if (count == pSmt->MaxLines - 1) {
count = pSmt->MaxTextLines - 1;
temp = pSmt->lines[0];
bottom = count;
if (pSmt->scrollback < pSmt->MaxScrollBack)
pSmt->scrollback += 1;
if (pSmt->scrollforward > 0)
pSmt->scrollforward -= 1;
}
else {
temp = pSmt->lines[pSmt->TopScroll];
bottom = pSmt->BottomScroll;
}
memmove(&pSmt->lines[pSmt->TopScroll],
&pSmt->lines[pSmt->TopScroll + 1],
count * sizeof (WORD *));
pSmt->lines[bottom] = temp;
}
else {
temp = pSmt->lines[pSmt->BottomScroll];
memmove(&pSmt->lines[pSmt->TopScroll + 1],
&pSmt->lines[pSmt->TopScroll],
count * sizeof (WORD *));
pSmt->lines[pSmt->TopScroll] = temp;
}
}
static void NEAR ComputeVisibleWindow(PSMT pSmt, short right, short bottom)
{
POINT Pt;
Pt.x = right;
Pt.y = bottom;
ClientToScreen(pSmt->hMain, &Pt);
ScreenToClient(pSmt->hStatic,&Pt);
pSmt->vrect.right = min((Pt.x /pSmt->CharWidth) * pSmt->CharWidth,
pSmt->rect.right);
if (pSmt->vrect.right <= 0)
pSmt->vrect.right = pSmt->CharWidth;
pSmt->vrect.bottom = min((Pt.y / pSmt->CharHeight) * pSmt->CharHeight,
pSmt->rect.bottom);
if (pSmt->vrect.bottom <= 0)
pSmt->vrect.bottom = pSmt->CharHeight;
}
static void NEAR AdjustWindowToCursor(PSMT pSmt)
{
register short Y2, Y;
POINT Pt;
short ypos;
HWND hWnd = pSmt->hWnd;
Y2 = pSmt->vrect.bottom - pSmt->CharHeight;
Pt.x = pSmt->Pos.x;
Pt.y = ypos = pSmt->Pos.y;
ClientToScreen(hWnd, &Pt);
ScreenToClient(pSmt->hStatic, &Pt);
Y = Pt.y;
if (Y > Y2) {
pSmt->rect.top = Y2 - ypos;
MoveWindow(hWnd,pSmt->rect.left, pSmt->rect.top,
pSmt->rect.right,pSmt->rect.bottom, TRUE);
}
else if (Y < 0) {
pSmt->rect.top = -ypos;
MoveWindow(hWnd,pSmt->rect.left, pSmt->rect.top,
pSmt->rect.right, pSmt->rect.bottom, TRUE);
}
}
static void NEAR wordmemset(WORD *dest, WORD val, int count)
{
/*
register WORD *wptr = dest;
register int i;
for (i = 0; i < count; i++)
*wptr++ = val;
*/
_asm {
pushf ; save direction flag
push di ; save pointer
cld
mov ax,ds ; set up es
mov es,ax
mov di,dest ; set destination pointer
mov ax,val ; value to set
mov cx,count ; number of words to store
rep stosw ; do it
pop di ; restore registers which must be saved
popf
}
}
short FAR PASCAL GetFontInfo(LPLOGFONT lf, LPTEXTMETRIC tm,
short type, LPSTR lpData)
{
SMT FAR *pSmt;
LPSTR dest;
LPSTR src;
register int i;
int width, height, weight;
BYTE charset;
static BOOL copied = FALSE;
if ((lf->lfPitchAndFamily & 3) != FIXED_PITCH)
return TRUE;
pSmt = (SMT FAR *)lpData;
dest = (LPSTR)&pSmt->lfnt;
src = (LPSTR)lf;
width = lf->lfWidth;
height = lf->lfHeight;
weight = lf->lfWeight;
charset = lf->lfCharSet;
if ((width == pSmt->NFontWidth) && (height == pSmt->NFontHeight)) {
if (weight == FW_BOLD)
pSmt->NBold = TRUE;
if (charset == SYMBOL_CHARSET)
pSmt->NSymbol = TRUE;
}
if ((width == pSmt->SFontWidth) && (height == pSmt->SFontHeight)) {
if (weight == FW_BOLD)
pSmt->SBold = TRUE;
if (charset == SYMBOL_CHARSET)
pSmt->SSymbol = TRUE;
}
if (!copied) {
for (i = 0; i < sizeof(LOGFONT); i++)
*(dest + i) = *(src + i);
copied = TRUE;
}
return TRUE;
}
HFONT FAR SetFontData(PSMT pSmt)
{
TEXTMETRIC TM;
HDC hDC;
HFONT hFont, hOldFont;
FARPROC fp;
HWND hWnd = pSmt->hMain;
hDC = GetDC(hWnd);
fp = MakeProcInstance((FARPROC)GetFontInfo,
GetWindowWord(hWnd,GWW_HINSTANCE));
EnumFonts(hDC, pSmt->lfnt.lfFaceName, fp, (LPSTR)pSmt);
FreeProcInstance(fp);
if (pSmt->MaxCols == MAXCOLUMNS) {
pSmt->lfnt.lfWidth = pSmt->SFontWidth;
pSmt->lfnt.lfHeight = pSmt->SFontHeight;
pSmt->Bold = pSmt->SBold;
} else {
pSmt->lfnt.lfWidth = pSmt->NFontWidth;
pSmt->lfnt.lfHeight = pSmt->NFontHeight;
pSmt->Bold = pSmt->NBold;
}
pSmt->lfnt.lfEscapement = 0;
pSmt->lfnt.lfOrientation = 0;
pSmt->lfnt.lfWeight = FW_NORMAL;
pSmt->lfnt.lfItalic = 0;
pSmt->lfnt.lfUnderline = 0;
pSmt->lfnt.lfStrikeOut = 0;
pSmt->lfnt.lfCharSet = ANSI_CHARSET;
hFont = CreateFontIndirect(&pSmt->lfnt);
hOldFont = SelectObject(hDC, hFont);
GetTextMetrics(hDC, &TM);
pSmt->CharHeight = TM.tmHeight + TM.tmExternalLeading;
pSmt->CharWidth = TM.tmAveCharWidth;
SelectObject(hDC, hOldFont);
ReleaseDC(pSmt->hMain, hDC);
return (hFont);
}