home *** CD-ROM | disk | FTP | other *** search
/ kermit.columbia.edu / kermit.columbia.edu.tar / kermit.columbia.edu / win100b / wktsmt.c < prev    next >
C/C++ Source or Header  |  1991-10-19  |  36KB  |  1,434 lines

  1. /*
  2.  * Smart terminal module
  3.  * 
  4.  * Copyright (c) 1990, 1991 by
  5.  * William S. Hall
  6.  * 3665 Benton Street  #66
  7.  * Santa Clara, CA 95051
  8.  *
  9.  */
  10.  
  11. #define NOSOUND
  12. #define NOCOMM
  13. #define NOKANJI
  14. #define NOATOM
  15. #include <windows.h>
  16. #if defined(WIN2)
  17. #define SYMBOL_CHARSET    2
  18. #include <winexp.h>
  19. #endif 
  20. #include <string.h>
  21. #include <ascii.h>
  22. #ifdef COLUMBIA
  23. #include "wktsmt.h"
  24. #else
  25. #include "smterm.h"
  26. #endif
  27.  
  28. static void NEAR TermWndPaint(PSMT pSmt, LPPAINTSTRUCT lpps);
  29. static int NEAR SmartTermDisplay(PSMT pSmt, BYTE *str, short len);
  30. static void NEAR ComputeVisibleWindow(PSMT pSmt, short right, short bottom);
  31. static void NEAR DoCR(PSMT pSmt);
  32. static void NEAR DoLF(PSMT pSmt);
  33. static void NEAR DoBS(PSMT pSmt);
  34. static void NEAR AdjustWindowToCursor(PSMT pSmt);
  35. static void NEAR CursorUp(PSMT pSmt, int count);
  36. static void NEAR CursorDown(PSMT pSmt, int count);
  37. static void NEAR CursorRight(PSMT pSmt, int count);
  38. static void NEAR CursorLeft(PSMT pSmt, int count);
  39. static void NEAR ClearToEndOfLine(PSMT pSmt);
  40. static void NEAR ClearToEndOfPage(PSMT pSmt);
  41. static void NEAR PositionCursor(PSMT pSmt, short r, short c);
  42. static void NEAR ReverseIndex(PSMT pSmt);
  43. static void NEAR DoHT(PSMT pSmt);
  44. static void NEAR AlignScreen(PSMT pSmt);
  45. static void NEAR ClearScreen(PSMT pSmt);
  46. static void NEAR SaveCursor(PSMT pSmt, BOOL flag);
  47. static void NEAR ClearToTopOfPage(PSMT pSmt);
  48. static void NEAR ClearToLineStart(PSMT pSmt);
  49. static void NEAR ClearLine(PSMT pSmt);
  50. static void NEAR ShowLineOfText(PSMT pSmt, HDC hDC, BYTE *str, short len,
  51.             short xpos, short ypos, BYTE attrib);
  52. static void NEAR InsertLine(PSMT pSmt, int count);
  53. static void NEAR DeleteLine(PSMT pSmt, int count);
  54. static void NEAR DeleteChar(PSMT pSmt, WORD count);
  55. static void NEAR SetTabStop(PSMT pSmt, LONG param);
  56. static void NEAR ChangeColors(PSMT pSmt, LONG *pColors);
  57. static void NEAR SetVideoAttrib(PSMT pSmt, WORD index);
  58. static void NEAR SetScrollRegion(PSMT pSmt, int top, int bottom);
  59. static void NEAR FillScreen(PSMT pSmt);
  60. static void NEAR SetScreen(PSMT pSmt, WORD rows, WORD cols);
  61. static long NEAR CalcScrollRange(PSMT pSmt, short xsize, short ysize);
  62. static void NEAR CopyLines(PSMT pSmt, short start, short end, LPSTR pbuf);
  63. static void NEAR FlipScreen(PSMT pSmt, short top, short bottom);
  64. static void NEAR SetCharSet(PSMT pSmt, WORD index);
  65. static void NEAR wordmemset(WORD *dest, WORD val, int count);
  66. static void NEAR scrollindex(PSMT pSmt, BOOL direction);
  67. static void NEAR SetOriginMode(PSMT pSmt, BOOL param);
  68. static void NEAR SmartTermCommand(register PSMT pSmt, 
  69.                   register WORD wParam, LONG lParam);
  70. static void NEAR SetFont(PSMT pSmt, SETFONT FAR *lplf);
  71. static void NEAR ScrollBack(PSMT pSmt, int lines, BOOL direction);
  72.  
  73. long FAR PASCAL SmartTermWndProc(HWND hWnd, unsigned message, 
  74.                  WORD wParam, LONG lParam)
  75. {
  76.  
  77.     register PSMT pSmt = (PSMT)GetWindowWord(hWnd,0);
  78.     PAINTSTRUCT ps;
  79.     long numrem;
  80.  
  81.     switch(message) {
  82.  
  83.     case SMT_STRINGINPUT:
  84.         HideCaret(hWnd);
  85.         numrem = SmartTermDisplay(pSmt,(BYTE *)LOWORD(lParam),(short)wParam);
  86.         SetCaretPos(pSmt->Pos.x, pSmt->Pos.y + pSmt->CharHeight);
  87.         ShowCaret(hWnd);
  88.         return ((LONG)numrem);
  89.         break;
  90.         
  91.     case SMT_COMMAND:
  92.         HideCaret(hWnd);
  93.         SmartTermCommand(pSmt, wParam, lParam);
  94.         SetCaretPos(pSmt->Pos.x, pSmt->Pos.y + pSmt->CharHeight);
  95.         ShowCaret(hWnd);
  96.         break;
  97.  
  98.     case SMT_SIZEPARENT:
  99.         ComputeVisibleWindow(pSmt, LOWORD(lParam), HIWORD(lParam));
  100.         MoveWindow(pSmt->hStatic, pSmt->vrect.left,
  101.                       pSmt->vrect.top,
  102.                       pSmt->vrect.right, 
  103.                           pSmt->vrect.bottom, TRUE);
  104.         pSmt->rect.left = pSmt->rect.top = 0;
  105.         MoveWindow(pSmt->hWnd,pSmt->rect.left, pSmt->rect.top,
  106.                pSmt->rect.right, pSmt->rect.bottom,TRUE);
  107.         AdjustWindowToCursor(pSmt);
  108.         return(CalcScrollRange(pSmt,(short)LOWORD(lParam),
  109.                    (short)HIWORD(lParam)));
  110.         break;    
  111.  
  112.     case SMT_CARETFUNCTION:
  113.         switch(wParam) {
  114.             case SM_CREATECARET:
  115.             if (HIWORD(lParam))
  116.                 CreateCaret(pSmt->hWnd,(HBITMAP)NULL,
  117.                     pSmt->CharWidth,-pSmt->CharHeight);
  118.             else
  119.                 CreateCaret(pSmt->hWnd,(HBITMAP)NULL,
  120.                             pSmt->CharWidth,-2);
  121.             SetCaretPos(pSmt->Pos.x, pSmt->Pos.y + pSmt->CharHeight);
  122.             if (LOWORD(lParam))
  123.                     ShowCaret(pSmt->hWnd);
  124.                 break;
  125.         case SM_DESTROYCARET:
  126.             HideCaret(pSmt->hWnd);
  127.             DestroyCaret();
  128.             break;
  129.         case SM_HIDECARET:
  130.             HideCaret(pSmt->hWnd);
  131.             break;
  132.         case SM_SHOWCARET:
  133.             ShowCaret(pSmt->hWnd);
  134.             break;
  135.         case SM_GETCARETPOS:
  136.             return(MAKELONG(1 + pSmt->Pos.y / pSmt->CharHeight,
  137.                         pSmt->CurLineOffset + 1));
  138.         }    
  139.         break;
  140.  
  141.         case SMT_SETATTRIBUTE:
  142.         switch(wParam) {
  143.         case SM_COLORCHANGE:
  144.             ChangeColors(pSmt, (LONG *)LOWORD(lParam));
  145.             break;
  146.         case SM_AUTOWRAP:
  147.             pSmt->Wrap = LOWORD(lParam);
  148.             break;
  149.         case SM_MARGINBELL:
  150.             pSmt->MarginBell = LOWORD(lParam);
  151.             break;
  152.         case SM_SMOOTHSCROLL:
  153.             pSmt->SmoothScroll = LOWORD(lParam);
  154.             break;
  155.         case SM_INSERT:
  156.             pSmt->ICToggle = LOWORD(lParam);
  157.             break;
  158.         case SM_SCROLLUNITS:
  159.             pSmt->ScrollUnits = LOWORD(lParam);
  160.             break;
  161.         }
  162.         break;
  163.  
  164.     case SMT_GETATTRIBUTE:
  165.         switch(wParam) {
  166.         case SM_AUTOWRAP:
  167.             return((LONG)pSmt->Wrap);
  168.             break;
  169.         case SM_MARGINBELL:
  170.             return((LONG)pSmt->MarginBell);
  171.             break;
  172.         case SM_SMOOTHSCROLL:
  173.             return((LONG)pSmt->SmoothScroll);
  174.             break;
  175.         case SM_SCREENSIZE:
  176.             return(MAKELONG(pSmt->MaxLines, pSmt->MaxCols));
  177.             break;
  178.         case SM_FONTFACE:
  179.             lstrcpy((LPSTR)lParam, pSmt->lfnt.lfFaceName);
  180.             return lstrlen(pSmt->lfnt.lfFaceName);
  181.         case SM_NORMALFONT:
  182.             return MAKELONG(pSmt->NFontWidth, pSmt->NFontHeight);
  183.         case SM_SMALLFONT:
  184.             return MAKELONG(pSmt->SFontWidth, pSmt->SFontHeight);
  185.         case SM_SCROLLUNITS:
  186.             return (LONG)pSmt->ScrollUnits;
  187.         }
  188.         break;
  189.  
  190.     case SMT_SHOWWINDOW:
  191.         ShowWindow(pSmt->hStatic, wParam);
  192.         break;
  193.  
  194.     case SMT_INVERT:
  195.         FlipScreen(pSmt, LOWORD(lParam), HIWORD(lParam));
  196.         break;
  197.  
  198.     case SMT_COPYLINES:
  199.         CopyLines(pSmt, (int)LOBYTE(wParam), (int)HIBYTE(wParam),
  200.                     (LPSTR)lParam);
  201.         break;
  202.  
  203.     case WM_CREATE:
  204.         SmartTermWndCreate(hWnd, lParam);
  205.         break;
  206.  
  207.     case WM_PAINT:
  208.             BeginPaint(hWnd, (LPPAINTSTRUCT)&ps);
  209.         TermWndPaint(pSmt, (LPPAINTSTRUCT)&ps);
  210.             EndPaint(hWnd, (LPPAINTSTRUCT)&ps);
  211.             break;
  212.  
  213.     case WM_ERASEBKGND:
  214.         SelectObject((HDC)wParam, pSmt->hbr);
  215.         FillRect((HDC)wParam, (LPRECT)&pSmt->rect, pSmt->hbr);
  216.         return (LONG)TRUE;
  217.  
  218.     case WM_DESTROY:
  219.         if (pSmt->hbr)
  220.         DeleteObject(pSmt->hbr);
  221.         if (pSmt->hFont)
  222.         DeleteObject(pSmt->hFont);
  223.         break;
  224.  
  225.      default:
  226.         return ((long)DefWindowProc(hWnd,message,wParam,lParam));
  227.         break;
  228.     }
  229.     return(0L);
  230. }    
  231.  
  232. static void NEAR SmartTermCommand(register PSMT pSmt, 
  233.                   register WORD wParam, LONG lParam)
  234. {
  235.  
  236.     switch(wParam) {
  237.     case SM_CURSORHOME:
  238.         pSmt->HaveToWrap = FALSE;
  239.         PositionCursor(pSmt, 0, 0);
  240.         break;
  241.     case SM_CURSORUP:
  242.         CursorUp(pSmt, LOWORD(lParam));
  243.         break;
  244.     case SM_CURSORDOWN:
  245.         CursorDown(pSmt, LOWORD(lParam));
  246.         break;
  247.     case SM_CURSORRIGHT:
  248.         CursorRight(pSmt, LOWORD(lParam));
  249.         break;
  250.     case SM_CURSORLEFT:
  251.         CursorLeft(pSmt, LOWORD(lParam));
  252.         break;
  253.     case SM_CLRTOENDOFLINE:
  254.         ClearToEndOfLine(pSmt);
  255.         break;
  256.     case SM_CLRTOENDOFPAGE:
  257.         ClearToEndOfLine(pSmt);
  258.         ClearToEndOfPage(pSmt);
  259.         break;
  260.     case SM_POSITIONCURSOR:
  261.         pSmt->HaveToWrap = FALSE;
  262.         PositionCursor(pSmt,(short)LOWORD(lParam) - 1,
  263.                     (short)HIWORD(lParam) - 1);
  264.         break;
  265.     case SM_REVERSEINDEX:
  266.         while (lParam--)
  267.             ReverseIndex(pSmt);
  268.         break;
  269.     case SM_INDEX:
  270.         while (lParam--)
  271.             DoLF(pSmt);
  272.         break;
  273.     case SM_NEXTLINE:
  274.         while (lParam--) {
  275.             DoCR(pSmt);
  276.             DoLF(pSmt);
  277.         }
  278.         break;
  279.     case SM_ALIGNSCREEN:
  280.         AlignScreen(pSmt);
  281.         break;
  282.     case SM_SAVECURSOR:
  283.         SaveCursor(pSmt, LOWORD(lParam));
  284.         break;
  285.     case SM_CLEARSCREEN:
  286.         ClearScreen(pSmt);
  287.         break;
  288.     case SM_CLEARTOTOPOFPAGE:
  289.         ClearToTopOfPage(pSmt);
  290.         ClearToLineStart(pSmt);
  291.         break;
  292.     case SM_CLEARTOLINESTART:
  293.         ClearToLineStart(pSmt);
  294.         break;
  295.     case SM_CLEARLINE:
  296.         ClearLine(pSmt);
  297.         break;
  298.     case SM_DELETECHAR:
  299.         DeleteChar(pSmt, LOWORD(lParam));
  300.         break;
  301.     case SM_INSERTLINE:
  302.         InsertLine(pSmt, LOWORD(lParam));
  303.         break;
  304.     case SM_DELETELINE:
  305.         DeleteLine(pSmt, LOWORD(lParam));
  306.         break;
  307.     case SM_SETTAB:
  308.         SetTabStop(pSmt, lParam);
  309.         break;
  310.     case SM_VIDEOATTRIB:
  311.         SetVideoAttrib(pSmt, LOWORD(lParam));
  312.         break;
  313.     case SM_SCROLLREGION:
  314.         SetScrollRegion(pSmt, LOWORD(lParam), HIWORD(lParam));
  315.         break;
  316.     case SM_FILLSCREEN:
  317.         FillScreen(pSmt);
  318.         break;
  319.     case SM_HSCROLL:
  320.         pSmt->rect.left = -LOWORD(lParam) * pSmt->CharWidth;
  321.         MoveWindow(pSmt->hWnd, pSmt->rect.left, pSmt->rect.top,
  322.          pSmt->rect.right, pSmt->rect.bottom, TRUE);
  323.         break;
  324.     case SM_SETCOLS:
  325.         SetScreen(pSmt, pSmt->MaxLines, LOWORD(lParam));
  326.         break;
  327.     case SM_LEFTMARGIN:
  328.         while (lParam--)
  329.             DoCR(pSmt);
  330.         break;
  331.     case SM_TAB:
  332.         while (lParam--)
  333.             DoHT(pSmt);
  334.         break;
  335.     case SM_BKSP:
  336.         while (lParam--)
  337.             DoBS(pSmt);
  338.         break;
  339.     case SM_SETCHARSET:
  340.         SetCharSet(pSmt, LOWORD(lParam));
  341.         break;
  342.     case SM_ORIGINMODE:
  343.         SetOriginMode(pSmt, LOWORD(lParam));
  344.         break;
  345.     case SM_SETFONT:
  346.         SetFont(pSmt, (SETFONT FAR *)lParam);
  347.         break;
  348.     case SM_SCROLLBACK:
  349.         ScrollBack(pSmt, LOWORD(lParam), (BOOL)HIWORD(lParam));
  350.         break;
  351.     case SM_PAGEBACK:
  352.         ScrollBack(pSmt, pSmt->MaxLines, (BOOL)HIWORD(lParam));
  353.         break;
  354.     case SM_HOMEEND:
  355.         ScrollBack(pSmt, pSmt->MaxTextLines, (BOOL)HIWORD(lParam));
  356.         break;
  357.     }
  358. }
  359.  
  360. static void NEAR ScrollBack(PSMT pSmt, int numlines, BOOL direction)
  361. {
  362.  
  363.     register int buflines = pSmt->MaxTextLines;
  364.     WORD *temp;
  365.     register int i;
  366.     
  367.     if (direction) {
  368.     numlines = min(numlines, pSmt->scrollback);
  369.         if (numlines > 0) {
  370.         for (i = 0; i < numlines; i++) {
  371.                 temp = pSmt->lines[buflines - 1];
  372.             memmove(&pSmt->lines[1],
  373.                 &pSmt->lines[0],
  374.                 (buflines - 1) * sizeof(WORD *));
  375.             pSmt->lines[0] = temp;
  376.         }
  377.         pSmt->scrollback -= numlines;
  378.         pSmt->scrollforward += numlines;
  379.             ScrollWindow(pSmt->hWnd,0,numlines * pSmt->CharHeight,
  380.              NULL,&pSmt->srect);
  381.             UpdateWindow(pSmt->hWnd);
  382.     }
  383.     }
  384.     else {
  385.     numlines = min(numlines, pSmt->scrollforward);
  386.     if (numlines > 0) {
  387.         for (i = 0; i < numlines; i++) {
  388.         temp = pSmt->lines[0];
  389.         memmove(&pSmt->lines[0],
  390.             &pSmt->lines[1],
  391.             (buflines - 1) * sizeof(WORD *));
  392.         pSmt->lines[buflines - 1] = temp;
  393.         }
  394.         pSmt->scrollback += numlines;
  395.         pSmt->scrollforward -= numlines;
  396.             ScrollWindow(pSmt->hWnd, 0, -numlines * pSmt->CharHeight, 
  397.              NULL, &pSmt->srect);
  398.             UpdateWindow(pSmt->hWnd);
  399.     }
  400.     }
  401. }
  402.  
  403. static void NEAR SetFont(PSMT pSmt, SETFONT FAR *lpsf)
  404. {
  405.  
  406.     RECT size;
  407.  
  408.     pSmt->NFontWidth = lpsf->nwidth;
  409.     pSmt->NFontHeight = lpsf->nheight;
  410.     pSmt->SFontWidth = lpsf->swidth;
  411.     pSmt->SFontHeight = lpsf->sheight;
  412.     lstrcpy(pSmt->lfnt.lfFaceName, lpsf->FaceName);
  413.     pSmt->hFont = SetFontData(pSmt);
  414.     pSmt->srect.right = pSmt->rect.right = pSmt->CharWidth * pSmt->MaxCols;
  415.     pSmt->srect.bottom = pSmt->rect.bottom = pSmt->CharHeight * pSmt->MaxLines;
  416.     PositionCursor(pSmt, pSmt->CurLine, pSmt->CurLineOffset);
  417.     GetClientRect(pSmt->hMain, &size);
  418.     PostMessage(pSmt->hMain, WM_SIZE, SIZENORMAL,
  419.         MAKELONG(size.right, size.bottom));
  420.  
  421. }
  422.  
  423. static void NEAR SetCharSet(PSMT pSmt, WORD index)
  424. {
  425.  
  426.     register BYTE hattrib = (BYTE)HIBYTE((int)pSmt->Attrib);
  427.  
  428.     if (index)
  429.     hattrib |= VA_SPECIAL;
  430.     else
  431.         hattrib &= ~VA_SPECIAL;
  432.  
  433.     pSmt->Attrib = 256 * hattrib;
  434. }
  435.  
  436. /* character deletion */
  437. static void NEAR DeleteChar(PSMT pSmt, WORD count)
  438. {
  439.  
  440.     RECT rect;
  441.     short offset = pSmt->CurLineOffset;
  442.     WORD *dest = pSmt->lines[pSmt->CurLine] + offset;
  443.     register short copycount;
  444.     register WORD maxdelchars;
  445.  
  446.     if (count > (maxdelchars = pSmt->MaxCols - offset))
  447.     count = maxdelchars;
  448.     copycount = maxdelchars - count;
  449.     memmove((BYTE *)dest, (BYTE *)(dest + count), copycount * sizeof (WORD));
  450.     wordmemset(dest + copycount, SP, count);
  451.  
  452.     SetRect(&rect, pSmt->Pos.x, pSmt->Pos.y,
  453.         pSmt->rect.right, pSmt->Pos.y + pSmt->CharHeight);
  454.     ScrollWindow(pSmt->hWnd,-pSmt->CharWidth * count, 0, &rect, &rect);
  455.     UpdateWindow(pSmt->hWnd);
  456. }
  457.  
  458. static void NEAR FlipScreen(PSMT pSmt, short top, short bottom)
  459. {
  460.  
  461.     register int i, j;
  462.     WORD mask = 256 * VA_MARK;
  463.     short cols = pSmt->MaxCols;
  464.     RECT rect;
  465.  
  466.     if ((top < 0) || (bottom > pSmt->MaxLines))
  467.     return;
  468.  
  469.     for (i = top; i <= bottom; i++)
  470.     for (j = 0; j < cols; j++)    
  471.         *(pSmt->lines[i] + j) ^= mask;
  472.  
  473.     rect.left = 0;
  474.     rect.right = pSmt->rect.right;
  475.     rect.top = top * pSmt->CharHeight;
  476.     rect.bottom = (bottom + 1) * pSmt->CharHeight;
  477.  
  478.     InvalidateRect(pSmt->hWnd, &rect, FALSE);
  479. }
  480.  
  481. static void NEAR CopyLines(PSMT pSmt, short start, short end, LPSTR pbuf)
  482. {
  483.  
  484.     register int i, j;
  485.     short cols = pSmt->MaxCols;
  486.     int count;
  487.  
  488.     for (i = start; i <= end; i++) {
  489.     for (j = cols - 1; (j >= 0) && (LOBYTE(*(pSmt->lines[i] + j)) == SP); j--)
  490.         ;
  491.     count = j + 1;
  492.     for (j = 0; j < count; j++)
  493.         *pbuf++ = LOBYTE(*(pSmt->lines[i] + j));
  494.     *pbuf++ = '\r';
  495.     *pbuf++ = '\n';
  496.     }
  497. }
  498.  
  499. static long NEAR CalcScrollRange(PSMT pSmt, short xsize, short ysize)
  500. {
  501.  
  502.     register short xrange, yrange;
  503.     short diff;
  504.  
  505.     diff = pSmt->rect.right - xsize;
  506.     if (diff > 0) {
  507.     xrange = diff / pSmt->CharWidth;
  508.     if (diff % pSmt->CharWidth)
  509.         xrange += 1;
  510.     }
  511.     else
  512.     xrange = 0;
  513.  
  514.     yrange = pSmt->rect.bottom - ysize;
  515.     yrange = (yrange > 0 ? (yrange / pSmt->CharHeight) : 0);
  516.     return MAKELONG(xrange, yrange);
  517. }
  518.  
  519. static void NEAR SetScreen(PSMT pSmt, WORD rows, WORD cols)
  520. {
  521.     short size = rows * cols;
  522.     HFONT hfont, holdfont;
  523.     HDC hDC;
  524.     TEXTMETRIC TM;
  525.     register int i,j;
  526.     
  527.     if (cols == MAXCOLUMNS) {
  528.     pSmt->lfnt.lfWidth = pSmt->SFontWidth;
  529.     pSmt->lfnt.lfHeight = pSmt->SFontHeight;
  530.     pSmt->Bold = pSmt->SBold;
  531.     pSmt->Symbol = pSmt->SSymbol;
  532.     }
  533.     else {
  534.     pSmt->lfnt.lfWidth = pSmt->NFontWidth;
  535.     pSmt->lfnt.lfHeight = pSmt->NFontHeight;
  536.     pSmt->Bold = pSmt->NBold;
  537.     pSmt->Symbol = pSmt->NSymbol;
  538.     }
  539.     hDC = GetDC(pSmt->hWnd);
  540.     hfont = CreateFontIndirect(&pSmt->lfnt);
  541.     holdfont = SelectObject(hDC, hfont);
  542.     GetTextMetrics(hDC, &TM);
  543.     pSmt->CharHeight = TM.tmHeight + TM.tmExternalLeading;
  544.     pSmt->CharWidth = TM.tmAveCharWidth;
  545.     SelectObject(hDC, holdfont);
  546.     ReleaseDC(pSmt->hWnd, hDC);
  547.  
  548.     if (pSmt->hFont)
  549.     DeleteObject(pSmt->hFont);
  550.     pSmt->hFont = hfont;
  551.  
  552.     pSmt->MaxCols = cols;
  553.     pSmt->MaxLines = rows;
  554.  
  555.     for (i = 0; i < MAXTEXTBUFFERS * pSmt->MaxLines; i++) {
  556.         pSmt->lines[i] = (pSmt->pVidBuffer + i * MAXCOLUMNS);
  557.         for (j = 0; j < MAXCOLUMNS; j++)
  558.         *(pSmt->lines[i] + j) = SP;
  559.     }
  560.     pSmt->scrollback = 0;
  561.     pSmt->scrollforward = 0;
  562.  
  563.     pSmt->TopScroll = pSmt->TopOrgLine = 0;
  564.     pSmt->BottomScroll = pSmt->BottomOrgLine = pSmt->MaxLines - 1;
  565.     pSmt->CurLine = 0;
  566.     pSmt->CurLineOffset = 0;
  567.     pSmt->Pos.x = pSmt->Pos.y = 0;
  568.     pSmt->rect.left = pSmt->rect.top = 0;
  569.     pSmt->srect.right = pSmt->rect.right = pSmt->CharWidth * pSmt->MaxCols;
  570.     pSmt->srect.bottom = pSmt->rect.bottom = pSmt->CharHeight * pSmt->MaxLines;
  571.     InvalidateRect(pSmt->hWnd, (LPRECT)NULL, TRUE);
  572. }
  573.  
  574. static void NEAR SetVideoAttrib(PSMT pSmt, WORD index)
  575. {
  576.     register BYTE hattrib = (BYTE)HIBYTE((int)pSmt->Attrib);
  577.     register BYTE special = (BYTE)(hattrib & VA_SPECIAL);
  578.  
  579.     switch(index) {
  580.     case 0:
  581.         hattrib = (BYTE)(VA_NORMAL | special);
  582.         break;
  583.     case 1:
  584.         hattrib |= VA_BOLD;
  585.         break;
  586.     case 4:
  587.         hattrib |= VA_UNDERLINE;
  588.         break;
  589.     case 5:
  590.         hattrib |= VA_BLINK;
  591.         break;
  592.     case 7:
  593.         hattrib |= VA_REVERSE;
  594.         break;
  595.     case 8:
  596.         hattrib |= VA_DIM;
  597.         break;
  598.     case 22:
  599.         hattrib &= ~VA_BOLD;
  600.         break;
  601.     case 24:
  602.         hattrib &= ~VA_UNDERLINE;
  603.         break;
  604.     case 25:
  605.         hattrib &= ~VA_BLINK;
  606.         break;
  607.     case 27:
  608.         hattrib &= ~VA_REVERSE;
  609.         break;
  610.     case 28:
  611.         hattrib &= ~VA_DIM;
  612.         break;
  613.     }    
  614.     pSmt->Attrib = 256 * hattrib;
  615. }
  616.  
  617. static void NEAR SetScrollRegion(PSMT pSmt, int top, int bottom)
  618. {
  619.  
  620.     register short max = pSmt->MaxLines;
  621.     register short cheight = pSmt->CharHeight;
  622.  
  623.     if ((top <= max) && (bottom <= max)) {
  624.         if (top == 0)
  625.         top = 1;
  626.         if (bottom == 0)
  627.         bottom = max;
  628.         if (top < bottom) {
  629.         pSmt->srect.top = cheight *  (top - 1);
  630.         pSmt->srect.bottom = cheight * bottom;
  631.         pSmt->TopScroll = top - 1;
  632.         pSmt->BottomScroll = bottom - 1;
  633.         if (pSmt->OriginMode)
  634.         SetOriginMode(pSmt, TRUE);
  635.         else
  636.            PositionCursor(pSmt, 0, 0);
  637.     }
  638.     }
  639. }
  640.  
  641. static void NEAR ChangeColors(register PSMT pSmt, LONG *pColors)
  642. {
  643.     pSmt->TextColor = pColors[0];
  644.     pSmt->BGColor = pColors[1];
  645.  
  646.     DeleteObject(pSmt->hbr);
  647.     pSmt->hbr = CreateSolidBrush(pSmt->BGColor);
  648.  
  649.     InvalidateRect(pSmt->hWnd, (LPRECT)NULL, TRUE);
  650. }
  651.  
  652. static void NEAR InsertLine(register PSMT pSmt, int count)
  653. {
  654.  
  655.     register int i;
  656.     WORD *save[MAXROWS];
  657.     RECT rect;
  658.     short top = pSmt->TopScroll;
  659.     short cur = pSmt->CurLine;
  660.     short bottom = pSmt->BottomScroll;
  661.     short len;
  662.  
  663.     if ((top <= cur) && (cur <= bottom)) {
  664.     count = min(bottom - cur + 1, count);
  665.     len = bottom - count + 1;
  666.     for (i = 0; i < count; i++) 
  667.         save[cur + i] = pSmt->lines[len + i];
  668.     for (i = bottom; i >= cur + count; i--) 
  669.         pSmt->lines[i] = pSmt->lines[i - count];
  670.     for (i = cur; i < cur + count; i++) {
  671.         pSmt->lines[i] = save[i];
  672.         wordmemset(pSmt->lines[i], SP, pSmt->MaxCols);
  673.     }        
  674.     DoCR(pSmt);
  675.         SetRect(&rect, 0, pSmt->Pos.y, pSmt->srect.right, pSmt->srect.bottom);
  676.         ScrollWindow(pSmt->hWnd, 0, count * pSmt->CharHeight, &rect, &rect);
  677.         UpdateWindow(pSmt->hWnd);
  678.     }
  679. }
  680.  
  681. static void NEAR DeleteLine(PSMT pSmt, int count)
  682. {
  683.  
  684.     register int i;
  685.     WORD *save[MAXROWS];
  686.     RECT rect;
  687.     short top = pSmt->TopScroll;
  688.     short cur = pSmt->CurLine;
  689.     short bottom = pSmt->BottomScroll;
  690.     short len;
  691.  
  692.     if ((top <= cur) && (cur <= bottom)) {
  693.     count = min(bottom - cur + 1, count);
  694.     len = bottom - count + 1;
  695.     for (i = 0; i < count; i++) 
  696.         save[len + i] = pSmt->lines[cur + i];
  697.     for (i = cur + count; i <= bottom; i++) 
  698.         pSmt->lines[i - count] = pSmt->lines[i];
  699.     for (i = len; i <= bottom; i++) {
  700.         pSmt->lines[i] = save[i];
  701.         wordmemset(pSmt->lines[i], SP, pSmt->MaxCols);
  702.     }        
  703.     DoCR(pSmt);
  704.         SetRect(&rect, 0, pSmt->Pos.y, pSmt->srect.right, pSmt->srect.bottom);
  705.     ScrollWindow(pSmt->hWnd, 0, -count * pSmt->CharHeight, &rect, &rect);
  706.         UpdateWindow(pSmt->hWnd);
  707.     }
  708. }
  709.  
  710. static void NEAR SaveCursor(PSMT pSmt, BOOL flag)
  711. {
  712.  
  713.     if (flag) {
  714.     pSmt->CurSaveX = pSmt->CurLineOffset;
  715.     pSmt->CurSaveY = pSmt->CurLine;
  716.     pSmt->SaveAttrib = pSmt->Attrib;
  717. //    pSmt->SaveCharSet = lfnt.lfCharSet;
  718.     }
  719.     else {
  720.     PositionCursor(pSmt, pSmt->CurSaveY, pSmt->CurSaveX);
  721.     pSmt->Attrib = pSmt->SaveAttrib;
  722. //    lfnt.lfCharSet = pSmt->SaveCharSet;
  723.     }
  724. }
  725.  
  726. static void NEAR SetTabStop(PSMT pSmt, LONG param)
  727. {
  728.     register BOOL set = LOWORD(param);
  729.     register WORD val = HIWORD(param);
  730.  
  731.     if (set)
  732.     pSmt->TabStops[pSmt->CurLineOffset] = 'T';
  733.     else {
  734.     if (val == 3)
  735.         memset(pSmt->TabStops, SP, MAXCOLUMNS); 
  736.     else if (val == 0)
  737.         pSmt->TabStops[pSmt->CurLineOffset] = SP;
  738.     }
  739. }
  740.  
  741. static void NEAR ClearToEndOfLine(PSMT pSmt)
  742. {
  743.     RECT rect;
  744.     register short offset = pSmt->CurLineOffset;
  745.     register short ypos = pSmt->Pos.y;
  746.  
  747.     wordmemset(pSmt->lines[pSmt->CurLine] + offset,SP,pSmt->MaxCols - offset);
  748.  
  749.     SetRect(&rect,pSmt->Pos.x,ypos,pSmt->rect.right,ypos + pSmt->CharHeight);
  750.     InvalidateRect(pSmt->hWnd, (LPRECT)&rect, TRUE);
  751.     UpdateWindow(pSmt->hWnd);
  752. }
  753.  
  754. static void NEAR ClearToLineStart(PSMT pSmt)
  755. {
  756.  
  757.     RECT rect;
  758.  
  759.     register short offset = pSmt->CurLineOffset+ 1;
  760.     register short width = offset * pSmt->CharWidth;
  761.  
  762.     wordmemset(pSmt->lines[pSmt->CurLine], SP, offset);
  763.  
  764.     SetRect(&rect, 0, pSmt->Pos.y, width, pSmt->Pos.y + pSmt->CharHeight);
  765.     InvalidateRect(pSmt->hWnd, (LPRECT)&rect, TRUE);
  766.     UpdateWindow(pSmt->hWnd);
  767.  
  768. }
  769.  
  770. static void NEAR ClearLine(PSMT pSmt)
  771. {
  772.  
  773.     RECT rect;
  774.  
  775.     wordmemset(pSmt->lines[pSmt->CurLine], SP, pSmt->MaxCols);
  776.     SetRect((LPRECT)&rect, 0, pSmt->Pos.y, pSmt->rect.right,
  777.                     pSmt->Pos.y + pSmt->CharHeight);
  778.     InvalidateRect(pSmt->hWnd, (LPRECT)&rect, TRUE);
  779.     UpdateWindow(pSmt->hWnd);
  780.  
  781. }
  782.  
  783. static void NEAR ClearToEndOfPage(PSMT pSmt)
  784. {
  785.  
  786.     RECT rect;
  787.     register int i;
  788.  
  789.     for (i = pSmt->CurLine; i < pSmt->MaxLines; i++)
  790.     wordmemset(pSmt->lines[i], SP, pSmt->MaxCols);
  791.  
  792.     SetRect(&rect, 0, pSmt->Pos.y + pSmt->CharHeight,
  793.             pSmt->rect.right, pSmt->rect.bottom);
  794.     InvalidateRect(pSmt->hWnd, &rect, TRUE);
  795.     UpdateWindow(pSmt->hWnd);
  796.  
  797. }
  798.  
  799. static void NEAR ClearToTopOfPage(PSMT pSmt)
  800. {
  801.     RECT rect;
  802.     register int i;
  803.  
  804.     for (i = 0; i < pSmt->CurLine; i++)
  805.     wordmemset(pSmt->lines[i], SP, pSmt->MaxCols);
  806.    
  807.     SetRect(&rect, 0, 0, pSmt->rect.right, pSmt->Pos.y);
  808.     InvalidateRect(pSmt->hWnd, &rect, TRUE);
  809.     UpdateWindow(pSmt->hWnd);
  810.  
  811. }
  812.  
  813. static void NEAR ClearScreen(PSMT pSmt)
  814. {
  815.     register int i;
  816.  
  817.     for (i = 0; i < pSmt->MaxLines; i++)
  818.         wordmemset(pSmt->lines[i], SP, pSmt->MaxCols);
  819.     InvalidateRect(pSmt->hWnd, NULL, TRUE);
  820.     UpdateWindow(pSmt->hWnd);
  821. }
  822.  
  823. static void NEAR AlignScreen(PSMT pSmt)
  824. {
  825.  
  826.     register int i;
  827.  
  828.     for (i = 0; i < pSmt->MaxLines; i++)
  829.         wordmemset(pSmt->lines[i], 'E', pSmt->MaxCols);
  830.     InvalidateRect(pSmt->hWnd, NULL, TRUE);
  831.     UpdateWindow(pSmt->hWnd);
  832.     PositionCursor(pSmt, 0, 0);
  833.  
  834. }
  835.  
  836. static void NEAR FillScreen(PSMT pSmt)
  837. {
  838.  
  839.     register int i,j;
  840.     BYTE ch = 0;
  841.  
  842.     for (i = 0; i < pSmt->MaxLines; i++)
  843.     for (j = 0; j < pSmt->MaxCols; j++)
  844.         *(pSmt->lines[i] + j) = (WORD)ch++;
  845.  
  846.     InvalidateRect(pSmt->hWnd, NULL, TRUE);
  847.     UpdateWindow(pSmt->hWnd);
  848.     PositionCursor(pSmt, 0, 0);
  849.  
  850. }
  851.  
  852. static void NEAR SetOriginMode(PSMT pSmt, BOOL param)
  853. {
  854.     if (param) {
  855.     pSmt->TopOrgLine = pSmt->TopScroll;
  856.     pSmt->BottomOrgLine = pSmt->BottomScroll;
  857.     }
  858.     else {
  859.     pSmt->TopOrgLine = 0;
  860.     pSmt->BottomOrgLine = (pSmt->MaxLines - 1);
  861.     }
  862.     pSmt->OriginMode = param;
  863.     PositionCursor(pSmt, 0, 0);
  864. }
  865.  
  866. static void NEAR PositionCursor(PSMT pSmt, short r, short c)
  867. {
  868.  
  869.     register short rows = pSmt->BottomOrgLine;
  870.     register short cols = pSmt->MaxCols;
  871.  
  872.     if (c >= cols)
  873.     c = cols - 1 ;
  874.     pSmt->Pos.x = c * pSmt->CharWidth;
  875.     pSmt->CurLineOffset = c;
  876.  
  877.     r += pSmt->TopOrgLine;
  878.     if (r > rows)
  879.     r = rows;
  880.     pSmt->Pos.y = r * pSmt->CharHeight;
  881.     pSmt->CurLine = r;
  882.  
  883.     AdjustWindowToCursor(pSmt);
  884. }
  885.  
  886. static int NEAR SmartTermDisplay(PSMT pSmt, BYTE *str, short len)
  887. {
  888.     
  889.     register BYTE *ptr;
  890.     register short ctr;
  891.     short cols = pSmt->MaxCols;
  892.     short cwidth = pSmt->CharWidth;
  893.     short width = pSmt->rect.right;
  894.     short txpos;
  895.     short toff;
  896.     WORD *tBuf;
  897.     WORD attrib = pSmt->Attrib;
  898.     WORD savebuf[MAXCOLUMNS];
  899.  
  900.     while (len > 0) {
  901.     ptr = str;
  902.     ctr = 0;
  903.     toff = pSmt->CurLineOffset;
  904.     if (pSmt->HaveToWrap && pSmt->Wrap && (toff == (cols - 1))) {
  905.         DoCR(pSmt);
  906.         DoLF(pSmt);
  907.         toff = pSmt->CurLineOffset;
  908.         pSmt->HaveToWrap = FALSE;
  909.     }
  910.     txpos = pSmt->Pos.x;
  911.     tBuf = pSmt->lines[pSmt->CurLine];
  912.  
  913.     while ((len > 0) && (toff < cols)) {
  914.         if (pSmt->ICToggle)
  915.             savebuf[ctr] = *(tBuf + toff);
  916.         *(tBuf + toff++) = *ptr++ + attrib;
  917.         if ((pSmt->MarginBell) && (toff == (cols - 8)))
  918.         MessageBeep(0);
  919.         ctr += 1;
  920.         txpos += cwidth;
  921.         len -= 1;
  922.     }
  923.     if (ctr) {
  924.         if (pSmt->ICToggle) {
  925.         RECT rect;
  926.         short ypos = pSmt->Pos.y;
  927.         short xpos = pSmt->Pos.x;
  928.         short tomove, tocopy;
  929.         tomove =  cols - toff - ctr;
  930.         tocopy = min (ctr, cols - toff);
  931.         if (tomove > 0)
  932.             memmove(tBuf + toff + ctr, tBuf + toff, tomove);
  933.         if (tocopy > 0)
  934.             strncpy((BYTE *)(tBuf + toff), 
  935.                     (BYTE *)savebuf, sizeof(WORD) * tocopy);
  936.         SetRect(&rect, xpos, ypos, width, ypos + pSmt->CharHeight);
  937.         ScrollWindow(pSmt->hWnd, txpos - xpos, 0, &rect, &rect);
  938.         UpdateWindow(pSmt->hWnd);
  939.         }
  940.         else {
  941.         HDC hDC = GetDC(pSmt->hWnd);
  942.         ShowLineOfText(pSmt,hDC,str,ctr,pSmt->Pos.x,pSmt->Pos.y,
  943.                         (BYTE)HIBYTE(attrib));
  944.         ReleaseDC(pSmt->hWnd, hDC);
  945.         }
  946.         if (toff < cols) {
  947.             pSmt->Pos.x = txpos;
  948.             pSmt->CurLineOffset = toff;
  949.         pSmt->HaveToWrap = FALSE;
  950.         }
  951.         else {
  952.             pSmt->CurLineOffset = (cols - 1);
  953.             pSmt->Pos.x = width - cwidth;
  954.         pSmt->HaveToWrap = TRUE;
  955.         }
  956.     }
  957.         str = ptr;
  958.     }
  959.     return (len);
  960. }
  961.  
  962. static void NEAR ShowLineOfText(PSMT pSmt, HDC hDC, BYTE *str, short len,
  963.             short xpos, short ypos, BYTE attrib)
  964. {
  965.  
  966.     HFONT hfont, holdfont;
  967.     register BOOL underline = attrib & VA_UNDERLINE;
  968.     register BOOL bold = (attrib & VA_BOLD) && pSmt->Bold;
  969.     BOOL special = (attrib & VA_SPECIAL) && pSmt->Symbol;
  970.  
  971.     if (attrib & VA_MARK) {
  972.     SetBkColor(hDC, ~pSmt->BGColor);
  973.     SetTextColor(hDC, ~pSmt->TextColor);
  974.     }
  975.     else if (attrib & VA_REVERSE) {
  976.     SetBkColor(hDC, pSmt->TextColor);
  977.     SetTextColor(hDC, pSmt->BGColor);
  978.     }
  979.     else {
  980.         SetBkColor(hDC, pSmt->BGColor);
  981.         SetTextColor(hDC, pSmt->TextColor);
  982.     }
  983.     if (bold || underline || special) {
  984.         pSmt->lfnt.lfUnderline = (BYTE)underline;
  985.         pSmt->lfnt.lfWeight = bold ? FW_BOLD : FW_NORMAL;
  986.     pSmt->lfnt.lfCharSet = (BYTE)(special ? SYMBOL_CHARSET : ANSI_CHARSET);
  987.         hfont = CreateFontIndirect(&pSmt->lfnt);
  988.     holdfont = SelectObject(hDC, hfont);
  989.     TextOut(hDC, xpos, ypos, (LPSTR)str, len);
  990.     SelectObject(hDC, holdfont);
  991.     DeleteObject(hfont);
  992.         pSmt->lfnt.lfUnderline = 0;
  993.         pSmt->lfnt.lfWeight = FW_NORMAL;
  994.     pSmt->lfnt.lfCharSet = ANSI_CHARSET;
  995.     }
  996.     else {
  997.         SelectObject(hDC, pSmt->hFont);
  998.         TextOut(hDC, xpos, ypos, (LPSTR)str, len);
  999.     }
  1000. }
  1001.  
  1002. static void NEAR CursorUp(PSMT pSmt, int count)
  1003. {
  1004.  
  1005.     register short d1 = pSmt->CurLine - pSmt->TopScroll;
  1006.     register short val;
  1007.  
  1008.     if (d1) {
  1009.     if (d1 > 0)
  1010.         val = min(count, d1);
  1011.     else
  1012.         val = min(count, pSmt->CurLine);
  1013.         pSmt->Pos.y -= val * pSmt->CharHeight;
  1014.         pSmt->CurLine -= val;
  1015.     AdjustWindowToCursor(pSmt);
  1016.     }
  1017. }
  1018. static void NEAR CursorDown(PSMT pSmt, int count)
  1019. {
  1020.  
  1021.     register short d1 = pSmt->BottomScroll - pSmt->CurLine;
  1022.     register short val;
  1023.  
  1024.     if (d1) {
  1025.     if (d1 > 0)
  1026.         val = min(count, d1);
  1027.     else
  1028.         val = min(count, pSmt->MaxLines - pSmt->CurLine - 1);
  1029.         pSmt->Pos.y += val * pSmt->CharHeight;
  1030.         pSmt->CurLine += val;
  1031.         AdjustWindowToCursor(pSmt);
  1032.     }
  1033. }
  1034.  
  1035. static void NEAR CursorRight(PSMT pSmt, int count)
  1036. {
  1037.     register short *offset = &pSmt->CurLineOffset;
  1038.     register int *xpos = &pSmt->Pos.x;
  1039.     short cols = pSmt->MaxCols - 1;
  1040.     short cwidth = pSmt->CharWidth;
  1041.  
  1042.     while ((*offset < cols) && (count--)) {
  1043.     *offset += 1;
  1044.     *xpos += cwidth;
  1045.     }
  1046. }
  1047.  
  1048. static void NEAR CursorLeft(PSMT pSmt, int count)
  1049. {
  1050.     register short *offset = &pSmt->CurLineOffset;
  1051.     register int *xpos = &pSmt->Pos.x;
  1052.     short cwidth = pSmt->CharWidth;
  1053.  
  1054.     while ((*offset > 0) && (count--)) {
  1055.     *offset -= 1;
  1056.     *xpos -= cwidth;
  1057.     }
  1058. }
  1059.         
  1060. static void NEAR DoCR(PSMT pSmt)
  1061. {
  1062.     pSmt->Pos.x = pSmt->CurLineOffset = 0;
  1063. }
  1064.  
  1065. static void NEAR DoHT(PSMT pSmt)
  1066. {
  1067.  
  1068.     register short *offset = &pSmt->CurLineOffset;
  1069.     register int *xpos;
  1070.     short cwidth;
  1071.     short cols = pSmt->MaxCols - 1;
  1072.     
  1073.     if (*offset >= cols)
  1074.     return;
  1075.  
  1076.     xpos = &pSmt->Pos.x;
  1077.     cwidth = pSmt->CharWidth;
  1078.  
  1079.     do {
  1080.     *offset += 1;
  1081.     *xpos += cwidth;
  1082.     } while ((pSmt->TabStops[*offset] != 'T') && (*offset < cols));
  1083. }
  1084.  
  1085. static void NEAR DoBS(PSMT pSmt)
  1086. {
  1087.     if (pSmt->CurLineOffset) {
  1088.     pSmt->CurLineOffset -= 1;
  1089.     pSmt->Pos.x -= pSmt->CharWidth;
  1090.     }
  1091. }
  1092.  
  1093. static void NEAR DoLF(PSMT pSmt)
  1094. {
  1095.  
  1096.     register int scrollrem;
  1097.  
  1098.     if (pSmt->CurLine == pSmt->BottomScroll) {
  1099.     scrollindex(pSmt, TRUE);
  1100.     wordmemset(pSmt->lines[pSmt->CurLine], SP, pSmt->MaxCols);
  1101.     if (pSmt->SmoothScroll) {
  1102.         for (scrollrem = pSmt->CharHeight;
  1103.          scrollrem >= pSmt->ScrollUnits;
  1104.          scrollrem -= pSmt->ScrollUnits) {
  1105.             ScrollWindow(pSmt->hWnd,0,-pSmt->ScrollUnits,NULL,&pSmt->srect);
  1106.             UpdateWindow(pSmt->hWnd);
  1107.         }
  1108.         if (scrollrem) {
  1109.             ScrollWindow(pSmt->hWnd,0,-scrollrem,NULL,&pSmt->srect);
  1110.             UpdateWindow(pSmt->hWnd);
  1111.         }
  1112. /*
  1113.         for (i = 0; i < pSmt->CharHeight/2; i++) {
  1114.             ScrollWindow(pSmt->hWnd,0, -2, NULL, &pSmt->srect);
  1115.             UpdateWindow(pSmt->hWnd);
  1116.         }
  1117.         if (pSmt->CharHeight & 1) {
  1118.         ScrollWindow(pSmt->hWnd,0, -1, NULL, &pSmt->srect);
  1119.         UpdateWindow(pSmt->hWnd);
  1120.         }
  1121. */
  1122.     }
  1123.     else {
  1124.             ScrollWindow(pSmt->hWnd,0,-pSmt->CharHeight, NULL, &pSmt->srect);
  1125.             UpdateWindow(pSmt->hWnd);
  1126.     }
  1127.     }
  1128.     else if (pSmt->CurLine < (pSmt->MaxLines - 1)) {
  1129.     pSmt->Pos.y += pSmt->CharHeight;
  1130.     pSmt->CurLine += 1;
  1131.         AdjustWindowToCursor(pSmt);
  1132.     }
  1133. }
  1134.  
  1135. static void NEAR ReverseIndex(PSMT pSmt)
  1136. {
  1137.  
  1138.     register int scrollrem;
  1139.  
  1140.     if (pSmt->CurLine == pSmt->TopScroll) {
  1141.     scrollindex(pSmt, FALSE);
  1142.     wordmemset(pSmt->lines[pSmt->CurLine], SP, pSmt->MaxCols);
  1143.     if (pSmt->SmoothScroll) {
  1144.         for (scrollrem = pSmt->CharHeight;
  1145.          scrollrem >= pSmt->ScrollUnits;
  1146.          scrollrem -= pSmt->ScrollUnits) {
  1147.             ScrollWindow(pSmt->hWnd,0,+pSmt->ScrollUnits,NULL,&pSmt->srect);
  1148.             UpdateWindow(pSmt->hWnd);
  1149.         }
  1150.         if (scrollrem) {
  1151.             ScrollWindow(pSmt->hWnd,0,+scrollrem,NULL,&pSmt->srect);
  1152.             UpdateWindow(pSmt->hWnd);
  1153.         }
  1154. /*
  1155.         for (i = 0; i < pSmt->CharHeight/2; i++) {
  1156.             ScrollWindow(pSmt->hWnd,0, 2, (LPRECT)NULL, &pSmt->srect);
  1157.             UpdateWindow(pSmt->hWnd);
  1158.         }
  1159.         if (pSmt->CharHeight & 1) {
  1160.         ScrollWindow(pSmt->hWnd, 0, 1, (LPRECT)NULL, &pSmt->srect);
  1161.         UpdateWindow(pSmt->hWnd);
  1162.         }
  1163. */
  1164.     }
  1165.     else {
  1166.             ScrollWindow(pSmt->hWnd,0, pSmt->CharHeight, NULL, &pSmt->srect);
  1167.             UpdateWindow(pSmt->hWnd);
  1168.     }
  1169.     }
  1170.     else if (pSmt->CurLine > 0) {
  1171.     pSmt->Pos.y -= pSmt->CharHeight;
  1172.     pSmt->CurLine -= 1;
  1173.         AdjustWindowToCursor(pSmt);
  1174.     }
  1175. }
  1176.  
  1177. static void NEAR TermWndPaint(PSMT pSmt, LPPAINTSTRUCT lpps)
  1178. {
  1179.  
  1180.     register int i,j, k;
  1181.     BYTE buf[MAXCOLUMNS];
  1182.     HDC hDC = lpps->hdc;
  1183.     RECT crect;
  1184.     BYTE attrib;
  1185.     short xpos;
  1186.     short cols = pSmt->MaxCols;
  1187.     short cheight = pSmt->CharHeight;
  1188.     short cwidth = pSmt->CharWidth;
  1189.     short count;
  1190.     short leftcol = 0;
  1191.     short leftbase = 0;
  1192.  
  1193.     if (!lpps->fErase) {
  1194.         SelectObject(hDC, pSmt->hbr);
  1195.     FillRect(hDC, (LPRECT)&lpps->rcPaint, pSmt->hbr);
  1196.     }
  1197.     crect.left = lpps->rcPaint.left;
  1198.     crect.right = lpps->rcPaint.right;
  1199.     crect.top = 0;
  1200.     crect.bottom = cheight;
  1201. /*
  1202.     if (crect.left > cwidth) {
  1203.     leftcol = crect.left / cwidth;
  1204.     leftbase = leftcol * cwidth;
  1205.     }
  1206. */
  1207.     for (j = 0; j < pSmt->MaxLines; j++) {
  1208.     if (RectVisible(hDC, &crect)) {
  1209.         k = 0;
  1210.         xpos = leftbase;
  1211.         attrib = (BYTE)HIBYTE(*pSmt->lines[j]);
  1212.         for (i = cols - 1; (i >= leftcol) && (*(pSmt->lines[j] + i) == SP); i--)
  1213.         ;
  1214.         count = i + 1;
  1215.         for (i = leftcol; i < count; i++) {
  1216.         if (attrib != (BYTE)HIBYTE(*(pSmt->lines[j] + i))) {
  1217.             ShowLineOfText(pSmt, hDC, buf, k, xpos, crect.top, attrib);
  1218.             xpos = cwidth * i;
  1219.             k = 0;
  1220.             attrib = (BYTE)HIBYTE(*(pSmt->lines[j] + i));
  1221.         }
  1222.         buf[k++] = (BYTE)LOBYTE(*(pSmt->lines[j] + i));
  1223.         }
  1224.         ShowLineOfText(pSmt, hDC, buf, k, xpos, crect.top, attrib);
  1225.     }
  1226.     crect.top += cheight;
  1227.     crect.bottom += cheight;
  1228.     }
  1229. }
  1230.  
  1231. static void NEAR scrollindex(PSMT pSmt, BOOL direction)
  1232. {
  1233.     register WORD *temp;
  1234.     int bottom;
  1235.     register int count = pSmt->BottomScroll - pSmt->TopScroll;
  1236.  
  1237.     if (direction) {
  1238.     if (count == pSmt->MaxLines - 1) {
  1239.         count = pSmt->MaxTextLines - 1;
  1240.         temp = pSmt->lines[0];
  1241.         bottom = count;
  1242.         if (pSmt->scrollback < pSmt->MaxScrollBack)
  1243.         pSmt->scrollback += 1;
  1244.         if (pSmt->scrollforward > 0)
  1245.         pSmt->scrollforward -= 1;
  1246.     }
  1247.     else {
  1248.         temp = pSmt->lines[pSmt->TopScroll];
  1249.         bottom = pSmt->BottomScroll;
  1250.     }
  1251.     memmove(&pSmt->lines[pSmt->TopScroll],
  1252.         &pSmt->lines[pSmt->TopScroll + 1],
  1253.         count * sizeof (WORD *));
  1254.     pSmt->lines[bottom] = temp;
  1255.     }
  1256.     else {
  1257.     temp = pSmt->lines[pSmt->BottomScroll];
  1258.     memmove(&pSmt->lines[pSmt->TopScroll + 1],
  1259.         &pSmt->lines[pSmt->TopScroll],
  1260.         count * sizeof (WORD *));
  1261.     pSmt->lines[pSmt->TopScroll] = temp;
  1262.     }
  1263. }
  1264.  
  1265. static void NEAR ComputeVisibleWindow(PSMT pSmt, short right, short bottom)
  1266. {
  1267.  
  1268.     POINT Pt;
  1269.  
  1270.     Pt.x = right;
  1271.     Pt.y = bottom;
  1272.  
  1273.     ClientToScreen(pSmt->hMain, &Pt);
  1274.     ScreenToClient(pSmt->hStatic,&Pt);
  1275.  
  1276.     pSmt->vrect.right = min((Pt.x /pSmt->CharWidth) * pSmt->CharWidth,
  1277.                  pSmt->rect.right);
  1278.  
  1279.     if (pSmt->vrect.right <= 0)
  1280.     pSmt->vrect.right = pSmt->CharWidth;
  1281.  
  1282.     pSmt->vrect.bottom = min((Pt.y / pSmt->CharHeight) * pSmt->CharHeight, 
  1283.                             pSmt->rect.bottom);
  1284.     if (pSmt->vrect.bottom <= 0)
  1285.     pSmt->vrect.bottom = pSmt->CharHeight;
  1286.  
  1287. }
  1288.  
  1289. static void NEAR AdjustWindowToCursor(PSMT pSmt)
  1290. {
  1291.  
  1292.     register short Y2, Y;
  1293.     POINT Pt;
  1294.     short ypos;
  1295.     HWND hWnd = pSmt->hWnd;
  1296.     
  1297.     Y2 = pSmt->vrect.bottom - pSmt->CharHeight;
  1298.  
  1299.     Pt.x = pSmt->Pos.x;
  1300.     Pt.y = ypos = pSmt->Pos.y;
  1301.  
  1302.     ClientToScreen(hWnd, &Pt);
  1303.     ScreenToClient(pSmt->hStatic, &Pt);
  1304.  
  1305.     Y = Pt.y;
  1306.  
  1307.     if (Y > Y2) {
  1308.     pSmt->rect.top = Y2 - ypos;
  1309.     MoveWindow(hWnd,pSmt->rect.left, pSmt->rect.top,
  1310.                 pSmt->rect.right,pSmt->rect.bottom, TRUE);
  1311.     }
  1312.     else if (Y < 0) {
  1313.     pSmt->rect.top = -ypos;
  1314.     MoveWindow(hWnd,pSmt->rect.left, pSmt->rect.top,
  1315.                 pSmt->rect.right, pSmt->rect.bottom, TRUE);
  1316.     }
  1317. }
  1318.  
  1319. static void NEAR wordmemset(WORD *dest, WORD val, int count)
  1320. {
  1321. /*
  1322.     register WORD *wptr = dest;
  1323.     register int i;
  1324.  
  1325.     for (i = 0; i < count; i++)
  1326.         *wptr++ = val;
  1327. */
  1328.  
  1329. _asm {
  1330.     pushf            ; save direction flag
  1331.     push    di        ; save pointer
  1332.     cld
  1333.  
  1334.     mov    ax,ds        ; set up es
  1335.     mov    es,ax
  1336.     mov    di,dest        ; set destination pointer
  1337.  
  1338.     mov    ax,val        ; value to set
  1339.     mov    cx,count    ; number of words to store
  1340.     rep    stosw        ; do it
  1341.     
  1342.     pop    di        ; restore registers which must be saved
  1343.     popf
  1344.       }
  1345. }
  1346.  
  1347. short FAR PASCAL GetFontInfo(LPLOGFONT lf, LPTEXTMETRIC tm, 
  1348.                  short type, LPSTR lpData)
  1349. {
  1350.  
  1351.     SMT FAR *pSmt;
  1352.     LPSTR dest;
  1353.     LPSTR src;
  1354.     register int i;
  1355.     int width, height, weight;
  1356.     BYTE charset;
  1357.     static BOOL copied = FALSE;
  1358.  
  1359.     if ((lf->lfPitchAndFamily & 3) != FIXED_PITCH)
  1360.     return TRUE;
  1361.  
  1362.     pSmt = (SMT FAR *)lpData;
  1363.     dest = (LPSTR)&pSmt->lfnt;
  1364.     src = (LPSTR)lf;
  1365.  
  1366.     width = lf->lfWidth;
  1367.     height = lf->lfHeight;
  1368.     weight = lf->lfWeight;
  1369.     charset = lf->lfCharSet;
  1370.  
  1371.     if ((width == pSmt->NFontWidth) && (height == pSmt->NFontHeight)) {
  1372.     if (weight == FW_BOLD)
  1373.         pSmt->NBold = TRUE;
  1374.     if (charset == SYMBOL_CHARSET)
  1375.         pSmt->NSymbol = TRUE;
  1376.     }
  1377.     if ((width == pSmt->SFontWidth) && (height == pSmt->SFontHeight)) {
  1378.     if (weight == FW_BOLD)
  1379.         pSmt->SBold = TRUE;
  1380.     if (charset == SYMBOL_CHARSET)
  1381.         pSmt->SSymbol = TRUE;
  1382.     }
  1383.  
  1384.     if (!copied) {
  1385.         for (i = 0; i < sizeof(LOGFONT); i++)
  1386.             *(dest + i) = *(src + i);
  1387.     copied = TRUE;
  1388.     }
  1389.     return TRUE;
  1390.  
  1391. }
  1392.  
  1393. HFONT FAR SetFontData(PSMT pSmt)
  1394. {
  1395.  
  1396.     TEXTMETRIC TM;
  1397.     HDC hDC;
  1398.     HFONT hFont, hOldFont;
  1399.     FARPROC fp;
  1400.     HWND hWnd = pSmt->hMain;
  1401.  
  1402.     hDC = GetDC(hWnd);
  1403.     fp = MakeProcInstance((FARPROC)GetFontInfo,
  1404.                GetWindowWord(hWnd,GWW_HINSTANCE));
  1405.     EnumFonts(hDC, pSmt->lfnt.lfFaceName, fp, (LPSTR)pSmt);
  1406.     FreeProcInstance(fp);
  1407.     if (pSmt->MaxCols == MAXCOLUMNS) {
  1408.         pSmt->lfnt.lfWidth = pSmt->SFontWidth;
  1409.         pSmt->lfnt.lfHeight = pSmt->SFontHeight;
  1410.     pSmt->Bold = pSmt->SBold;
  1411.     } else {
  1412.         pSmt->lfnt.lfWidth = pSmt->NFontWidth;
  1413.         pSmt->lfnt.lfHeight = pSmt->NFontHeight;
  1414.     pSmt->Bold = pSmt->NBold;
  1415.     }
  1416.     pSmt->lfnt.lfEscapement = 0;
  1417.     pSmt->lfnt.lfOrientation = 0;
  1418.     pSmt->lfnt.lfWeight = FW_NORMAL;
  1419.     pSmt->lfnt.lfItalic = 0;
  1420.     pSmt->lfnt.lfUnderline = 0;
  1421.     pSmt->lfnt.lfStrikeOut = 0;
  1422.     pSmt->lfnt.lfCharSet = ANSI_CHARSET;
  1423.     hFont = CreateFontIndirect(&pSmt->lfnt);
  1424.     hOldFont = SelectObject(hDC, hFont);
  1425.     GetTextMetrics(hDC, &TM);
  1426.     pSmt->CharHeight = TM.tmHeight + TM.tmExternalLeading;
  1427.     pSmt->CharWidth = TM.tmAveCharWidth;
  1428.     SelectObject(hDC, hOldFont);
  1429.     ReleaseDC(pSmt->hMain, hDC);
  1430.  
  1431.     return (hFont);
  1432.  
  1433. }
  1434.