home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Graphics / Plotting / aa_Intel_Only / Gnuplot / Unused / win / wtext.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-12  |  46.2 KB  |  1,727 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: wtext.c%v 3.38.2.74 1993/02/19 01:19:51 woo Exp woo $";
  3. #endif
  4.  
  5. /* GNUPLOT - win/wtext.c */
  6. /*
  7.  * Copyright (C) 1992   Russell Lang
  8.  *
  9.  * Permission to use, copy, and distribute this software and its
  10.  * documentation for any purpose with or without fee is hereby granted, 
  11.  * provided that the above copyright notice appear in all copies and 
  12.  * that both that copyright notice and this permission notice appear 
  13.  * in supporting documentation.
  14.  *
  15.  * Permission to modify the software is granted, but not the right to
  16.  * distribute the modified code.  Modifications are to be distributed 
  17.  * as patches to released version.
  18.  *  
  19.  * This software is provided "as is" without express or implied warranty.
  20.  * 
  21.  *
  22.  * AUTHORS
  23.  * 
  24.  *   Russell Lang
  25.  * 
  26.  * Send your comments or suggestions to 
  27.  *  info-gnuplot@dartmouth.edu.
  28.  * This is a mailing list; to join it send a note to 
  29.  *  info-gnuplot-request@dartmouth.edu.  
  30.  * Send bug reports to
  31.  *  bug-gnuplot@dartmouth.edu.
  32.  */
  33.  
  34. /* WARNING: Do not write to stdout/stderr with functions not listed 
  35.    in win/wtext.h */
  36.  
  37. #define STRICT
  38. #include <windows.h>
  39. #include <windowsx.h>
  40. #if WINVER >= 0x030a
  41. #include <commdlg.h>
  42. #endif
  43. #include <string.h>    /* use only far items */
  44. #ifndef __MSC__
  45. #include <mem.h>
  46. #endif
  47. #include <stdlib.h>
  48. #include <ctype.h>
  49. #include <dos.h>
  50.  
  51. #include "wgnuplib.h"
  52. #include "wresourc.h"
  53. #include "wcommon.h"
  54.  
  55. /* font stuff */
  56. #define TEXTFONTSIZE 9
  57. #define TEXTFONTNAME "Terminal"
  58.  
  59. #define EOF -1        /* instead of using <stdio.h> */
  60. /* limits */
  61. #define MAXSTR 256
  62. POINT ScreenMinSize = {16,4};
  63. LRESULT CALLBACK _export WndParentProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
  64. LRESULT CALLBACK _export WndTextProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
  65. void ReadTextIni(LPTW lptw);
  66. void LimitMark(LPTW lptw, POINT FAR *lppt);
  67.  
  68. char szNoMemory[] = "out of memory";
  69. COLORREF TextColorTable[16] = { 
  70.     RGB(0,0,0),            /* black */
  71.     RGB(0,0,128),        /* dark blue */
  72.     RGB(0,128,0),        /* dark green */
  73.     RGB(0,128,128),        /* dark cyan */
  74.     RGB(128,0,0),        /* dark red */
  75.     RGB(128,0,128),        /* dark magenta */
  76.     RGB(128,128,0),        /* dark yellow */
  77.     RGB(128,128,128),    /* dark grey */
  78.     RGB(192,192,192),    /* light grey */
  79.     RGB(0,0,255),        /* blue */
  80.     RGB(0,255,0),        /* green */
  81.     RGB(0,255,255),        /* cyan */
  82.     RGB(255,0,0),        /* red */
  83.     RGB(255,0,255),        /* magenta */
  84.     RGB(255,255,0),        /* yellow */
  85.     RGB(255,255,255),    /* white */
  86. };
  87. #define NOTEXT 0xF0
  88. #define MARKFORE RGB(255,255,255)
  89. #define MARKBACK RGB(0,0,128)
  90. #define TextFore(attr) TextColorTable[(attr) & 15]
  91. #define TextBack(attr) TextColorTable[(attr>>4) & 15]
  92.  
  93.  
  94. void WDPROC
  95. TextMessage(void)
  96. {
  97.     MSG msg;
  98.  
  99.     while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
  100.         {
  101.         TranslateMessage(&msg);
  102.         DispatchMessage(&msg);
  103.         }
  104.     return;
  105. }
  106.  
  107.  
  108.  
  109. void
  110. CreateTextClass(LPTW lptw)
  111. {
  112. WNDCLASS wndclass;
  113.     wndclass.style = CS_HREDRAW | CS_VREDRAW;
  114.     wndclass.lpfnWndProc = WndTextProc;
  115.     wndclass.cbClsExtra = 0;
  116.     wndclass.cbWndExtra = 2 * sizeof(void FAR *);
  117.     wndclass.hInstance = lptw->hInstance;
  118.     wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  119.     wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  120.     wndclass.hbrBackground = GetStockBrush(WHITE_BRUSH);
  121.     wndclass.lpszMenuName = NULL;
  122.     wndclass.lpszClassName = szTextClass;
  123.     RegisterClass(&wndclass);
  124.  
  125.     wndclass.style = CS_HREDRAW | CS_VREDRAW;
  126.     wndclass.lpfnWndProc = WndParentProc;
  127.     wndclass.cbClsExtra = 0;
  128.     wndclass.cbWndExtra = sizeof(void FAR *);
  129.     wndclass.hInstance = lptw->hInstance;
  130.     if (lptw->hIcon)
  131.         wndclass.hIcon = lptw->hIcon;
  132.     else
  133.         wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  134.     wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  135.     wndclass.hbrBackground = GetStockBrush(WHITE_BRUSH);
  136.     wndclass.lpszMenuName = NULL;
  137.     wndclass.lpszClassName = szParentClass;
  138.     RegisterClass(&wndclass);
  139. }
  140.  
  141.  
  142. /* make text window */
  143. int WDPROC
  144. TextInit(LPTW lptw)
  145. {
  146.     RECT rect;
  147.     HMENU sysmenu;
  148.     HGLOBAL hglobal;
  149.     char buf[80];
  150.     
  151.     if (!lptw->hPrevInstance)
  152.         CreateTextClass(lptw);
  153.  
  154.     if (lptw->KeyBufSize == 0)
  155.         lptw->KeyBufSize = 256;
  156.  
  157.     if (lptw->ScreenSize.x < ScreenMinSize.x)
  158.         lptw->ScreenSize.x = ScreenMinSize.x;
  159.     if (lptw->ScreenSize.y < ScreenMinSize.y)
  160.         lptw->ScreenSize.y = ScreenMinSize.y;
  161.  
  162.     lptw->CursorPos.x = lptw->CursorPos.y = 0;
  163.     lptw->bFocus = FALSE;
  164.     lptw->bGetCh = FALSE;
  165.     lptw->CaretHeight = 0;
  166.     if (!lptw->nCmdShow)
  167.         lptw->nCmdShow = SW_SHOWNORMAL;
  168.     if (!lptw->Attr)
  169.         lptw->Attr = 0xf0;    /* black on white */
  170.  
  171.     hglobal = GlobalAlloc(GHND, lptw->ScreenSize.x * lptw->ScreenSize.y);
  172.     lptw->ScreenBuffer = (BYTE FAR *)GlobalLock(hglobal);
  173.     if (lptw->ScreenBuffer == (BYTE FAR *)NULL) {
  174.         MessageBox((HWND)NULL,szNoMemory,(LPSTR)NULL, MB_ICONHAND | MB_SYSTEMMODAL);
  175.         return(1);
  176.     }
  177.     _fmemset(lptw->ScreenBuffer, ' ', lptw->ScreenSize.x * lptw->ScreenSize.y);
  178.     hglobal = GlobalAlloc(GHND, lptw->ScreenSize.x * lptw->ScreenSize.y);
  179.     lptw->AttrBuffer = (BYTE FAR *)GlobalLock(hglobal);
  180.     if (lptw->AttrBuffer == (BYTE FAR *)NULL) {
  181.         MessageBox((HWND)NULL,szNoMemory,(LPSTR)NULL, MB_ICONHAND | MB_SYSTEMMODAL);
  182.         return(1);
  183.     }
  184.     _fmemset(lptw->AttrBuffer, NOTEXT, lptw->ScreenSize.x * lptw->ScreenSize.y);
  185.     hglobal = GlobalAlloc(LHND, lptw->KeyBufSize);
  186.     lptw->KeyBuf = (BYTE FAR *)GlobalLock(hglobal);
  187.     if (lptw->KeyBuf == (BYTE FAR *)NULL) {
  188.         MessageBox((HWND)NULL,szNoMemory,(LPSTR)NULL, MB_ICONHAND | MB_SYSTEMMODAL);
  189.         return(1);
  190.     }
  191.     lptw->KeyBufIn = lptw->KeyBufOut = lptw->KeyBuf;
  192.  
  193.     ReadTextIni(lptw);
  194.  
  195.     lptw->hWndParent = CreateWindow(szParentClass, lptw->Title,
  196.           WS_OVERLAPPEDWINDOW,
  197.           lptw->Origin.x, lptw->Origin.y,
  198.           lptw->Size.x, lptw->Size.y,
  199.           NULL, NULL, lptw->hInstance, lptw);
  200.     if (lptw->hWndParent == (HWND)NULL) {
  201.         MessageBox((HWND)NULL,"Couldn't open parent text window",(LPSTR)NULL, MB_ICONHAND | MB_SYSTEMMODAL);
  202.         return(1);
  203.     }
  204.     ShowWindow(lptw->hWndParent, lptw->nCmdShow);
  205.     GetClientRect(lptw->hWndParent, &rect);
  206.  
  207.     lptw->hWndText = CreateWindow(szTextClass, lptw->Title,
  208.           WS_CHILD | WS_VSCROLL | WS_HSCROLL,
  209.           0, lptw->ButtonHeight,
  210.           rect.right, rect.bottom-lptw->ButtonHeight,
  211.           lptw->hWndParent, NULL, lptw->hInstance, lptw);
  212.     if (lptw->hWndText == (HWND)NULL) {
  213.         MessageBox((HWND)NULL,"Couldn't open text window",(LPSTR)NULL, MB_ICONHAND | MB_SYSTEMMODAL);
  214.         return(1);
  215.     }
  216.  
  217.     lptw->hPopMenu = CreatePopupMenu();
  218.     AppendMenu(lptw->hPopMenu, MF_STRING, M_COPY_CLIP, "&Copy to Clipboard");
  219.     AppendMenu(lptw->hPopMenu, MF_STRING, M_PASTE, "&Paste");
  220. #if WINVER >= 0x030a
  221.     AppendMenu(lptw->hPopMenu, MF_STRING, M_CHOOSE_FONT, "Choose &Font...");
  222. #endif
  223.     if (lptw->IniFile != (LPSTR)NULL) {
  224.         wsprintf(buf,"&Update %s",lptw->IniFile);
  225.         AppendMenu(lptw->hPopMenu, MF_STRING, M_WRITEINI, (LPSTR)buf);
  226.     }
  227.  
  228.     sysmenu = GetSystemMenu(lptw->hWndParent,0);    /* get the sysmenu */
  229.     AppendMenu(sysmenu, MF_SEPARATOR, 0, NULL);
  230.     AppendMenu(sysmenu, MF_POPUP, (UINT)lptw->hPopMenu, "&Options");
  231.     AppendMenu(sysmenu, MF_STRING, M_ABOUT, "&About");
  232.  
  233.     if (lptw->lpmw)
  234.         LoadMacros(lptw);
  235.  
  236.     ShowWindow(lptw->hWndText, SW_SHOWNORMAL);
  237.     BringWindowToTop(lptw->hWndText);
  238.     SetFocus(lptw->hWndText);
  239.     TextMessage();
  240.     return(0);
  241. }
  242.  
  243. /* close a text window */
  244. void WDPROC
  245. TextClose(LPTW lptw)
  246. {
  247.     HGLOBAL hglobal;
  248.  
  249.     /* close window */
  250.     if (lptw->hWndParent)
  251.         DestroyWindow(lptw->hWndParent);
  252.     TextMessage();
  253.  
  254.     hglobal = (HGLOBAL)GlobalHandle( SELECTOROF(lptw->ScreenBuffer) );
  255.     if (hglobal) {
  256.         GlobalUnlock(hglobal);
  257.         GlobalFree(hglobal);
  258.     }
  259.     hglobal = (HGLOBAL)GlobalHandle( SELECTOROF(lptw->AttrBuffer) );
  260.     if (hglobal) {
  261.         GlobalUnlock(hglobal);
  262.         GlobalFree(hglobal);
  263.     }
  264.     hglobal = (HGLOBAL)GlobalHandle( SELECTOROF(lptw->KeyBuf) );
  265.     if (hglobal) {
  266.         GlobalUnlock(hglobal);
  267.         GlobalFree(hglobal);
  268.     }
  269.  
  270.     if (lptw->lpmw)
  271.         CloseMacros(lptw);
  272.     lptw->hWndParent = (HWND)NULL;
  273. }
  274.     
  275. void
  276. WriteTextIni(LPTW lptw)
  277. {
  278.     RECT rect;
  279.     LPSTR file = lptw->IniFile;
  280.     LPSTR section = lptw->IniSection;
  281.     char profile[80];
  282.     int iconic;
  283.  
  284.     
  285.     if ((file == (LPSTR)NULL) || (section == (LPSTR)NULL))
  286.         return;
  287.     
  288.     iconic = IsIconic(lptw->hWndParent);
  289.     if (iconic)
  290.         ShowWindow(lptw->hWndParent, SW_SHOWNORMAL);
  291.     GetWindowRect(lptw->hWndParent,&rect);
  292.     wsprintf(profile, "%d %d", rect.left, rect.top);
  293.     WritePrivateProfileString(section, "TextOrigin", profile, file);
  294.     wsprintf(profile, "%d %d", rect.right-rect.left, rect.bottom-rect.top);
  295.     WritePrivateProfileString(section, "TextSize", profile, file);
  296.     wsprintf(profile, "%d", iconic);
  297.     WritePrivateProfileString(section, "TextMinimized", profile, file);
  298.     wsprintf(profile, "%s,%d", lptw->fontname, lptw->fontsize);
  299.     WritePrivateProfileString(section, "TextFont", profile, file);
  300.     if (iconic)
  301.         ShowWindow(lptw->hWndParent, SW_SHOWMINIMIZED);
  302.     return;
  303. }
  304.  
  305. void
  306. ReadTextIni(LPTW lptw)
  307. {
  308.     LPSTR file = lptw->IniFile;
  309.     LPSTR section = lptw->IniSection;
  310.     char profile[81];
  311.     LPSTR p;
  312.     BOOL bOKINI;
  313.  
  314.     bOKINI = (file != (LPSTR)NULL) && (section != (LPSTR)NULL);
  315.     profile[0] = '\0';
  316.  
  317.     if (bOKINI)
  318.       GetPrivateProfileString(section, "TextOrigin", "", profile, 80, file);
  319.     if ( (p = GetInt(profile, &lptw->Origin.x)) == NULL)
  320.         lptw->Origin.x = CW_USEDEFAULT;
  321.     if ( (p = GetInt(p, &lptw->Origin.y)) == NULL)
  322.         lptw->Origin.y = CW_USEDEFAULT;
  323.     if ( (file != (LPSTR)NULL) && (section != (LPSTR)NULL) )
  324.       GetPrivateProfileString(section, "TextSize", "", profile, 80, file);
  325.     if ( (p = GetInt(profile, &lptw->Size.x)) == NULL)
  326.         lptw->Size.x = CW_USEDEFAULT;
  327.     if ( (p = GetInt(p, &lptw->Size.y)) == NULL)
  328.         lptw->Size.y = CW_USEDEFAULT;
  329.  
  330.     if (bOKINI)
  331.       GetPrivateProfileString(section, "TextFont", "", profile, 80, file);
  332.     {
  333.         char FAR *size;
  334.         size = _fstrchr(profile,',');
  335.         if (size) {
  336.             *size++ = '\0';
  337.             if ( (p = GetInt(size, &lptw->fontsize)) == NULL)
  338.                 lptw->fontsize = TEXTFONTSIZE;
  339.         }
  340.         _fstrcpy(lptw->fontname, profile);
  341.         if (lptw->fontsize == 0)
  342.             lptw->fontsize = TEXTFONTSIZE;
  343.         if (!(*lptw->fontname))
  344.             _fstrcpy(lptw->fontname,TEXTFONTNAME);
  345.     }
  346.  
  347.     if (bOKINI) {
  348.         int iconic;
  349.         GetPrivateProfileString(section, "TextMinimized", "", profile, 80, file);
  350.         if ( (p = GetInt(profile, &iconic)) == NULL)
  351.             iconic = 0;
  352.         if (iconic)
  353.             lptw->nCmdShow = SW_SHOWMINIMIZED;
  354.     }
  355. }
  356.  
  357.  
  358. /* Bring Cursor into text window */
  359. void WDPROC
  360. TextToCursor(LPTW lptw)
  361. {
  362. int nXinc=0;
  363. int nYinc=0;
  364. int cxCursor;
  365. int cyCursor;
  366.     cyCursor = lptw->CursorPos.y * lptw->CharSize.y;
  367.     if ( (cyCursor + lptw->CharSize.y > lptw->ScrollPos.y + lptw->ClientSize.y) 
  368.       || (cyCursor < lptw->ScrollPos.y) ) {
  369.         nYinc = max(0, cyCursor + lptw->CharSize.y - lptw->ClientSize.y) - lptw->ScrollPos.y;
  370.         nYinc = min(nYinc, lptw->ScrollMax.y - lptw->ScrollPos.y);
  371.     }
  372.     cxCursor = lptw->CursorPos.x * lptw->CharSize.x;
  373.     if ( (cxCursor + lptw->CharSize.x > lptw->ScrollPos.x + lptw->ClientSize.x)
  374.       || (cxCursor < lptw->ScrollPos.x) ) {
  375.         nXinc = max(0, cxCursor + lptw->CharSize.x - lptw->ClientSize.x/2) - lptw->ScrollPos.x;
  376.         nXinc = min(nXinc, lptw->ScrollMax.x - lptw->ScrollPos.x);
  377.     }
  378.     if (nYinc || nXinc) {
  379.         lptw->ScrollPos.y += nYinc;
  380.         lptw->ScrollPos.x += nXinc;
  381.         ScrollWindow(lptw->hWndText,-nXinc,-nYinc,NULL,NULL);
  382.         SetScrollPos(lptw->hWndText,SB_VERT,lptw->ScrollPos.y,TRUE);
  383.         SetScrollPos(lptw->hWndText,SB_HORZ,lptw->ScrollPos.x,TRUE);
  384.         UpdateWindow(lptw->hWndText);
  385.     }
  386. }
  387.  
  388. void
  389. NewLine(LPTW lptw)
  390. {
  391.     lptw->CursorPos.x = 0;
  392.     lptw->CursorPos.y++;
  393.     if (lptw->CursorPos.y >= lptw->ScreenSize.y) {
  394.         int i =  lptw->ScreenSize.x * (lptw->ScreenSize.y - 1);
  395.         _fmemmove(lptw->ScreenBuffer, lptw->ScreenBuffer+lptw->ScreenSize.x, i);
  396.         _fmemset(lptw->ScreenBuffer + i, ' ', lptw->ScreenSize.x);
  397.         _fmemmove(lptw->AttrBuffer, lptw->AttrBuffer+lptw->ScreenSize.x, i);
  398.         _fmemset(lptw->AttrBuffer + i, NOTEXT, lptw->ScreenSize.x);
  399.         lptw->CursorPos.y--;
  400.         ScrollWindow(lptw->hWndText,0,-lptw->CharSize.y,NULL,NULL);
  401.         lptw->MarkBegin.y--;
  402.         lptw->MarkEnd.y--;
  403.         LimitMark(lptw, &lptw->MarkBegin);
  404.         LimitMark(lptw, &lptw->MarkEnd);
  405.         UpdateWindow(lptw->hWndText);
  406.     }
  407.     if (lptw->CursorFlag)
  408.         TextToCursor(lptw);
  409.     TextMessage();
  410. }
  411.  
  412. /* Update count characters in window at cursor position */
  413. /* Updates cursor position */
  414. void
  415. UpdateText(LPTW lptw, int count)
  416. {
  417. HDC hdc;
  418. int xpos, ypos;
  419.     xpos = lptw->CursorPos.x*lptw->CharSize.x - lptw->ScrollPos.x;
  420.     ypos = lptw->CursorPos.y*lptw->CharSize.y - lptw->ScrollPos.y;
  421.     hdc = GetDC(lptw->hWndText);
  422.     SetTextColor(hdc, TextFore(lptw->Attr));
  423.     SetBkColor(hdc, TextBack(lptw->Attr));
  424.     SelectFont(hdc, lptw->hfont);
  425.     TextOut(hdc,xpos,ypos,
  426.         (LPSTR)(lptw->ScreenBuffer + lptw->CursorPos.y*lptw->ScreenSize.x + 
  427.         lptw->CursorPos.x), count);
  428.     (void)ReleaseDC(lptw->hWndText,hdc);
  429.     lptw->CursorPos.x += count;
  430.     if (lptw->CursorPos.x >= lptw->ScreenSize.x)
  431.         NewLine(lptw);
  432. }
  433.  
  434. int WDPROC
  435. TextPutCh(LPTW lptw, BYTE ch)
  436. {
  437. int pos;
  438.     switch(ch) {
  439.         case '\r':
  440.             lptw->CursorPos.x = 0;
  441.             if (lptw->CursorFlag)
  442.                 TextToCursor(lptw);
  443.             break;
  444.         case '\n':
  445.             NewLine(lptw);
  446.             break;
  447.         case 7:
  448.             MessageBeep(-1);
  449.             if (lptw->CursorFlag)
  450.                 TextToCursor(lptw);
  451.             break;
  452.         case '\t':
  453.             {
  454.             int n;
  455.                 for ( n = 8 - (lptw->CursorPos.x % 8); n>0; n-- )
  456.                     TextPutCh(lptw, ' ');
  457.             }
  458.             break;
  459.         case 0x08:
  460.         case 0x7f:
  461.             lptw->CursorPos.x--;
  462.             if (lptw->CursorPos.x < 0) {
  463.                 lptw->CursorPos.x = lptw->ScreenSize.x - 1;
  464.                 lptw->CursorPos.y--;
  465.             }
  466.             if (lptw->CursorPos.y < 0)
  467.                 lptw->CursorPos.y = 0;
  468.             break;
  469.         default:
  470.             pos = lptw->CursorPos.y*lptw->ScreenSize.x + lptw->CursorPos.x;
  471.             lptw->ScreenBuffer[pos] = ch;
  472.             lptw->AttrBuffer[pos] = lptw->Attr;
  473.             UpdateText(lptw, 1);
  474.     }
  475.     return ch;
  476. }
  477.  
  478. void 
  479. TextPutStr(LPTW lptw, LPSTR str)
  480. {
  481. BYTE FAR *p, FAR *pa;
  482. int count, limit;
  483.     while (*str) {
  484.         p = lptw->ScreenBuffer + lptw->CursorPos.y*lptw->ScreenSize.x + lptw->CursorPos.x;
  485.         pa = lptw->AttrBuffer + lptw->CursorPos.y*lptw->ScreenSize.x + lptw->CursorPos.x;
  486.         limit = lptw->ScreenSize.x - lptw->CursorPos.x;
  487.         for (count=0; (count < limit) && *str && (isprint(*str) || *str=='\t'); count++) {
  488.             if (*str=='\t') {
  489.                 int n;
  490.                 for ( n = 8 - ((lptw->CursorPos.x+count) % 8); (count < limit) & (n>0); n--, count++ ) {
  491.                     *p++ = ' ';
  492.                     *pa++ = lptw->Attr;
  493.                 }
  494.                 str++;
  495.                 count--;
  496.             }
  497.             else {
  498.                 *p++ = *str++;
  499.                 *pa++ = lptw->Attr;
  500.             }
  501.         }
  502.         if (count>0) {
  503.             UpdateText(lptw, count);
  504.         }
  505.         if (*str=='\n') {
  506.             NewLine(lptw);
  507.             str++;
  508.         }
  509.         else if (*str && !isprint(*str) && *str!='\t') {
  510.             TextPutCh(lptw, *str++);
  511.         }
  512.     }
  513. }
  514.  
  515.  
  516. void
  517. LimitMark(LPTW lptw, POINT FAR *lppt)
  518. {
  519.     if (lppt->x < 0)
  520.         lppt->x = 0;
  521.     if (lppt->y < 0) {
  522.         lppt->x = 0;
  523.         lppt->y = 0;
  524.     }
  525.     if (lppt->x > lptw->ScreenSize.x)
  526.         lppt->x = lptw->ScreenSize.x;
  527.     if (lppt->y >= lptw->ScreenSize.y) {
  528.         lppt->x = 0;
  529.         lppt->y = lptw->ScreenSize.y;
  530.     }
  531. }
  532.  
  533. void
  534. ClearMark(LPTW lptw, POINT pt)
  535. {
  536. RECT rect1, rect2, rect3;
  537. int tmp;
  538.   if ((lptw->MarkBegin.x != lptw->MarkEnd.x) || 
  539.       (lptw->MarkBegin.y != lptw->MarkEnd.y) ) {
  540.     if (lptw->MarkBegin.x > lptw->MarkEnd.x) {
  541.         tmp = lptw->MarkBegin.x;
  542.         lptw->MarkBegin.x = lptw->MarkEnd.x;
  543.         lptw->MarkEnd.x = tmp;
  544.     }
  545.     if (lptw->MarkBegin.y > lptw->MarkEnd.y) {
  546.         tmp = lptw->MarkBegin.y;
  547.         lptw->MarkBegin.y = lptw->MarkEnd.y;
  548.         lptw->MarkEnd.y = tmp;
  549.     }
  550.     /* calculate bounding rectangle in character coordinates */
  551.     if (lptw->MarkBegin.y != lptw->MarkEnd.y) {
  552.         rect1.left = 0;
  553.         rect1.right = lptw->ScreenSize.x;
  554.     }
  555.     else {
  556.         rect1.left = lptw->MarkBegin.x;
  557.         rect1.right = lptw->MarkEnd.x + 1;
  558.     }
  559.     rect1.top = lptw->MarkBegin.y;
  560.     rect1.bottom = lptw->MarkEnd.y + 1;
  561.     /* now convert to client coordinates */
  562.     rect1.left   = rect1.left   * lptw->CharSize.x - lptw->ScrollPos.x;
  563.     rect1.right  = rect1.right  * lptw->CharSize.x - lptw->ScrollPos.x;
  564.     rect1.top    = rect1.top    * lptw->CharSize.y - lptw->ScrollPos.y;
  565.     rect1.bottom = rect1.bottom * lptw->CharSize.y - lptw->ScrollPos.y;
  566.     /* get client rect and calculate intersection */
  567.     GetClientRect(lptw->hWndText, &rect2);
  568.     IntersectRect(&rect3,  &rect1, &rect2);
  569.     /* update window if necessary */
  570.     if (!IsRectEmpty(&rect3)) {
  571.         InvalidateRect(lptw->hWndText, &rect3, TRUE);
  572.     }
  573.   }
  574.   LimitMark(lptw, &pt);
  575.   lptw->MarkBegin.x = lptw->MarkEnd.x = pt.x;
  576.   lptw->MarkBegin.y = lptw->MarkEnd.y = pt.y;
  577.   UpdateWindow(lptw->hWndText);
  578. }
  579.  
  580.  
  581. /* output a line including attribute changes as needed */
  582. void
  583. DoLine(LPTW lptw, HDC hdc, int xpos, int ypos, int offset, int count)
  584. {
  585.     BYTE FAR *pa, attr;
  586.     int idx, num;
  587.     pa = lptw->AttrBuffer + offset;
  588. if ((offset < 0) || (offset >= lptw->ScreenSize.x*lptw->ScreenSize.y))
  589. MessageBox((HWND)NULL, "panic", "panic", MB_OK | MB_ICONEXCLAMATION);
  590.     idx = 0;
  591.     num = count;
  592.     while (num > 0) {
  593.         attr = *pa;
  594.         while ((num > 0) && (attr == *pa)) {
  595.             /* skip over bytes with same attribute */
  596.             num--;
  597.             pa++;
  598.         }
  599.         SetTextColor(hdc, TextFore(attr));
  600.         SetBkColor(hdc, TextBack(attr));
  601.         TextOut(hdc,xpos,ypos, (LPSTR)(lptw->ScreenBuffer + offset + idx),
  602.             count-num-idx);
  603.         xpos += lptw->CharSize.x * (count-num-idx);
  604.         idx = count-num;
  605.     }
  606. }
  607.  
  608. void
  609. DoMark(LPTW lptw, POINT pt, POINT end, BOOL mark)
  610. {
  611. int xpos, ypos;
  612. HDC hdc;
  613. int count;
  614. int offset;
  615.     offset = lptw->ScreenSize.x * pt.y + pt.x;
  616.     hdc = GetDC(lptw->hWndText);
  617.     SelectFont(hdc, lptw->hfont);
  618.     SetTextColor(hdc, MARKFORE);
  619.     SetBkColor(hdc, MARKBACK);
  620.     while (pt.y < end.y) {
  621.         /* multiple lines */
  622.         xpos = pt.x*lptw->CharSize.x - lptw->ScrollPos.x;
  623.         ypos = pt.y*lptw->CharSize.y - lptw->ScrollPos.y;
  624.         count = lptw->ScreenSize.x - pt.x;
  625.         if (mark)
  626.             TextOut(hdc,xpos,ypos, (LPSTR)(lptw->ScreenBuffer + offset), count);
  627.         else {
  628.             DoLine(lptw, hdc, xpos, ypos, offset, count);
  629.             SetTextColor(hdc, MARKFORE);
  630.             SetBkColor(hdc, MARKBACK);
  631.         }
  632.         offset += count;
  633.         pt.y++;
  634.         pt.x=0;
  635.     }
  636.     /* partial line */
  637.     xpos = pt.x*lptw->CharSize.x - lptw->ScrollPos.x;
  638.     ypos = pt.y*lptw->CharSize.y - lptw->ScrollPos.y;
  639.     count = end.x - pt.x;
  640.     if (end.y != lptw->ScreenSize.y) {
  641.         if (mark)
  642.             TextOut(hdc,xpos,ypos, (LPSTR)(lptw->ScreenBuffer + offset), count);
  643.         else
  644.             DoLine(lptw, hdc, xpos, ypos, offset, count);
  645.     }
  646.     (void)ReleaseDC(lptw->hWndText,hdc);
  647. }
  648.  
  649. void
  650. UpdateMark(LPTW lptw, POINT pt)
  651. {
  652. int begin, point, end;
  653.     LimitMark(lptw, &pt);
  654.     begin = lptw->ScreenSize.x*lptw->MarkBegin.y + lptw->MarkBegin.x;
  655.     point = lptw->ScreenSize.x*pt.y + pt.x;
  656.     end   = lptw->ScreenSize.x*lptw->MarkEnd.y + lptw->MarkEnd.x;
  657.  
  658.     if (begin <= end) {
  659.         /* forward mark */
  660.         if (point >= end) {
  661.             /* extend marked area */
  662.             DoMark(lptw, lptw->MarkEnd, pt, TRUE);
  663.         }
  664.         else if (point >= begin) {
  665.             /* retract marked area */
  666.             DoMark(lptw, pt, lptw->MarkEnd, FALSE);
  667.         }
  668.         else {    /* retract and reverse */
  669.             DoMark(lptw, lptw->MarkBegin, lptw->MarkEnd, FALSE);
  670.             DoMark(lptw, pt, lptw->MarkBegin, TRUE);
  671.         }
  672.     }
  673.     else {
  674.         /* reverse mark */
  675.         if (point <= end) {
  676.             /* extend marked area */
  677.             DoMark(lptw, pt, lptw->MarkEnd, TRUE);
  678.         }
  679.         else if (point <= begin) {
  680.             /* retract marked area */
  681.             DoMark(lptw, lptw->MarkEnd, pt, FALSE);
  682.         }
  683.         else {    /* retract and reverse */
  684.             DoMark(lptw, lptw->MarkEnd, lptw->MarkBegin, FALSE);
  685.             DoMark(lptw, lptw->MarkBegin, pt, TRUE);
  686.         }
  687.     }
  688.     lptw->MarkEnd.x = pt.x;
  689.     lptw->MarkEnd.y = pt.y;
  690. }
  691.  
  692.  
  693. #if WINVER >= 0x030a
  694. /* Windows 3.1 drag-drop feature */
  695. char szFile[80];
  696. void
  697. DragFunc(LPTW lptw, HDROP hdrop)
  698. {
  699.     int i, cFiles;
  700.     LPSTR p;
  701.     if ( (lptw->DragPre==(LPSTR)NULL) || (lptw->DragPost==(LPSTR)NULL) )
  702.         return;
  703.     cFiles = DragQueryFile(hdrop, 0xffff, (LPSTR)NULL, 0);
  704.     for (i=0; i<cFiles; i++) {
  705.         DragQueryFile(hdrop, i, szFile, 80);
  706.         for (p=lptw->DragPre; *p; p++)
  707.             SendMessage(lptw->hWndText,WM_CHAR,*p,1L);
  708.         for (p=szFile; *p; p++)
  709.             SendMessage(lptw->hWndText,WM_CHAR,*p,1L);
  710.         for (p=lptw->DragPost; *p; p++)
  711.             SendMessage(lptw->hWndText,WM_CHAR,*p,1L);
  712.     }
  713.     DragFinish(hdrop);
  714. }
  715. #endif
  716.  
  717.  
  718. void
  719. TextCopyClip(LPTW lptw)
  720. {
  721.     int size, count;
  722.     HGLOBAL hGMem;
  723.     LPSTR cbuf, cp;
  724.     POINT pt, end;
  725.     TEXTMETRIC tm;
  726.     UINT type;
  727.     HDC hdc;
  728.  
  729.     if ((lptw->MarkBegin.x == lptw->MarkEnd.x) && 
  730.         (lptw->MarkBegin.y == lptw->MarkEnd.y) ) {
  731.         /* copy user text */
  732.         return;
  733.     }
  734.  
  735.     size = (lptw->MarkEnd.y - lptw->MarkBegin.y + 1) 
  736.         * (lptw->ScreenSize.x + 2) + 1;
  737.     hGMem = GlobalAlloc(GMEM_MOVEABLE, (DWORD)size);
  738.     cbuf = cp = (LPSTR)GlobalLock(hGMem);
  739.     if (cp == (LPSTR)NULL)
  740.         return;
  741.     
  742.     pt.x = lptw->MarkBegin.x;
  743.     pt.y = lptw->MarkBegin.y;
  744.     end.x   = lptw->MarkEnd.x;
  745.     end.y   = lptw->MarkEnd.y;
  746.  
  747.     while (pt.y < end.y) {
  748.         /* copy to global buffer */
  749.         count = lptw->ScreenSize.x - pt.x;
  750.         _fmemcpy(cp, lptw->ScreenBuffer + lptw->ScreenSize.x*pt.y+pt.x, count);
  751.         /* remove trailing spaces */
  752.         for (count=count-1; count>=0; count--) {
  753.             if (cp[count]!=' ')
  754.                 break;
  755.             cp[count] = '\0';
  756.         }
  757.         cp[++count] = '\r';
  758.         cp[++count] = '\n';
  759.         cp[++count] = '\0';
  760.         cp += count;
  761.         pt.y++;
  762.         pt.x=0;
  763.     }
  764.     /* partial line */
  765.     count = end.x - pt.x;
  766.     if (end.y != lptw->ScreenSize.y) {
  767.         _fmemcpy(cp, lptw->ScreenBuffer + lptw->ScreenSize.x*pt.y+pt.x, count);
  768.         cp[count] = '\0';
  769.     }
  770.     size = _fstrlen(cbuf) + 1;
  771.     GlobalUnlock(hGMem);
  772.     hGMem = GlobalReAlloc(hGMem, (DWORD)size, GMEM_MOVEABLE);
  773.     /* find out what type to put into clipboard */
  774.     hdc = GetDC(lptw->hWndText);
  775.     SelectFont(hdc, lptw->hfont);
  776.     GetTextMetrics(hdc,(TEXTMETRIC FAR *)&tm);
  777.     if (tm.tmCharSet == OEM_CHARSET)
  778.         type = CF_OEMTEXT;
  779.     else
  780.         type = CF_TEXT;
  781.     ReleaseDC(lptw->hWndText, hdc);
  782.     /* give buffer to clipboard */
  783.     OpenClipboard(lptw->hWndParent);
  784.     EmptyClipboard();
  785.     SetClipboardData(type, hGMem);
  786.     CloseClipboard();
  787. }
  788.  
  789. void
  790. TextMakeFont(LPTW lptw)
  791. {
  792.     LOGFONT lf;
  793.     TEXTMETRIC tm;
  794.     LPSTR p;
  795.     HDC hdc;
  796.  
  797.     hdc = GetDC(lptw->hWndText);
  798.     _fmemset(&lf, 0, sizeof(LOGFONT));
  799.     _fstrncpy(lf.lfFaceName,lptw->fontname,LF_FACESIZE);
  800.     lf.lfHeight = -MulDiv(lptw->fontsize, GetDeviceCaps(hdc, LOGPIXELSY), 72);
  801.     lf.lfPitchAndFamily = FIXED_PITCH;
  802.     lf.lfCharSet = DEFAULT_CHARSET;
  803.     if ( (p = _fstrstr(lptw->fontname," Italic")) != (LPSTR)NULL ) {
  804.         lf.lfFaceName[ (unsigned int)(p-lptw->fontname) ] = '\0';
  805.         lf.lfItalic = TRUE;
  806.     }
  807.     if ( (p = _fstrstr(lptw->fontname," Bold")) != (LPSTR)NULL ) {
  808.         lf.lfFaceName[ (unsigned int)(p-lptw->fontname) ] = '\0';
  809.         lf.lfWeight = FW_BOLD;
  810.     }
  811.     if (lptw->hfont != 0)
  812.         DeleteFont(lptw->hfont);
  813.     lptw->hfont = CreateFontIndirect((LOGFONT FAR *)&lf);
  814.     /* get text size */
  815.     SelectFont(hdc, lptw->hfont);
  816.     GetTextMetrics(hdc,(TEXTMETRIC FAR *)&tm);
  817.     lptw->CharSize.y = tm.tmHeight;
  818.     lptw->CharSize.x = tm.tmAveCharWidth;
  819.     lptw->CharAscent = tm.tmAscent;
  820.     if (lptw->bFocus)
  821.         CreateCaret(lptw->hWndText, 0, lptw->CharSize.x, 2+lptw->CaretHeight);
  822.     ReleaseDC(lptw->hWndText, hdc);
  823.     return;
  824. }
  825.  
  826. void
  827. TextSelectFont(LPTW lptw) {
  828. #if WINVER >= 0x030a
  829.     LOGFONT lf;
  830.     CHOOSEFONT cf;
  831.     HDC hdc;
  832.     char lpszStyle[LF_FACESIZE]; 
  833.     LPSTR p;
  834.  
  835.     /* Set all structure fields to zero. */
  836.     _fmemset(&cf, 0, sizeof(CHOOSEFONT));
  837.     _fmemset(&lf, 0, sizeof(LOGFONT));
  838.     cf.lStructSize = sizeof(CHOOSEFONT);
  839.     cf.hwndOwner = lptw->hWndParent;
  840.     _fstrncpy(lf.lfFaceName,lptw->fontname,LF_FACESIZE);
  841.     if ( (p = _fstrstr(lptw->fontname," Bold")) != (LPSTR)NULL ) {
  842.         _fstrncpy(lpszStyle,p+1,LF_FACESIZE);
  843.         lf.lfFaceName[ (unsigned int)(p-lptw->fontname) ] = '\0';
  844.     }
  845.     else if ( (p = _fstrstr(lptw->fontname," Italic")) != (LPSTR)NULL ) {
  846.         _fstrncpy(lpszStyle,p+1,LF_FACESIZE);
  847.         lf.lfFaceName[ (unsigned int)(p-lptw->fontname) ] = '\0';
  848.     }
  849.     else
  850.         _fstrcpy(lpszStyle,"Regular");
  851.     cf.lpszStyle = lpszStyle;
  852.     hdc = GetDC(lptw->hWndText);
  853.     lf.lfHeight = -MulDiv(lptw->fontsize, GetDeviceCaps(hdc, LOGPIXELSY), 72);
  854.     ReleaseDC(lptw->hWndText, hdc);
  855.     lf.lfPitchAndFamily = FIXED_PITCH;
  856.     cf.lpLogFont = &lf;
  857.     cf.nFontType = SCREEN_FONTTYPE;
  858.     cf.Flags = CF_SCREENFONTS | CF_FIXEDPITCHONLY | CF_INITTOLOGFONTSTRUCT | CF_USESTYLE;
  859.     if (ChooseFont(&cf)) {
  860.         RECT rect;
  861.         _fstrcpy(lptw->fontname,lf.lfFaceName);
  862.         lptw->fontsize = cf.iPointSize / 10;
  863.         if (cf.nFontType & BOLD_FONTTYPE)
  864.             lstrcat(lptw->fontname," Bold");
  865.         if (cf.nFontType & ITALIC_FONTTYPE)
  866.             lstrcat(lptw->fontname," Italic");
  867.         TextMakeFont(lptw);
  868.         /* force a window update */
  869.         GetClientRect(lptw->hWndText, (LPRECT) &rect);
  870.         SendMessage(lptw->hWndText, WM_SIZE, SIZE_RESTORED, 
  871.             MAKELPARAM(rect.right-rect.left, rect.bottom-rect.top));
  872.         GetClientRect(lptw->hWndText, (LPRECT) &rect);
  873.         InvalidateRect(lptw->hWndText, (LPRECT) &rect, 1);
  874.         UpdateWindow(lptw->hWndText);
  875.     }
  876. #endif
  877. }
  878.  
  879.  
  880. /* parent overlapped window */
  881. LRESULT CALLBACK _export
  882. WndParentProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  883. {
  884.     HDC hdc;
  885.     PAINTSTRUCT ps;
  886.     RECT rect;
  887.     LPTW lptw;
  888.  
  889.     lptw = (LPTW)GetWindowLong(hwnd, 0);
  890.  
  891.     switch(message) {
  892.         case WM_SYSCOMMAND:
  893.             switch(LOWORD(wParam))
  894.             {
  895.                 case M_COPY_CLIP:
  896.                 case M_PASTE:
  897.                 case M_CHOOSE_FONT:
  898.                 case M_WRITEINI:
  899.                 case M_ABOUT:
  900.                   SendMessage(lptw->hWndText, WM_COMMAND, wParam, lParam);
  901.             }
  902.             break;
  903.         case WM_SETFOCUS: 
  904.             if (IsWindow(lptw->hWndText)) {
  905.                 SetFocus(lptw->hWndText);
  906.                 return(0);
  907.             }
  908.             break;
  909.         case WM_GETMINMAXINFO:
  910.             {
  911.             POINT far * MMinfo = (POINT far *)lParam;
  912.             TEXTMETRIC tm;
  913.             hdc = GetDC(hwnd);
  914.             SelectFont(hdc, GetStockFont(OEM_FIXED_FONT));
  915.             GetTextMetrics(hdc,(LPTEXTMETRIC)&tm);
  916.             ReleaseDC(hwnd,hdc);
  917.             /* minimum size */
  918.             MMinfo[3].x = ScreenMinSize.x*tm.tmAveCharWidth
  919.                 + GetSystemMetrics(SM_CXVSCROLL) + 2*GetSystemMetrics(SM_CXFRAME);
  920.             MMinfo[3].y = ScreenMinSize.y*tm.tmHeight
  921.                 + GetSystemMetrics(SM_CYHSCROLL) + 2*GetSystemMetrics(SM_CYFRAME)
  922.                 + GetSystemMetrics(SM_CYCAPTION);
  923.             }
  924.             return(0);
  925.         case WM_SIZE:
  926.             SetWindowPos(lptw->hWndText, (HWND)NULL, 0, lptw->ButtonHeight,
  927.                 LOWORD(lParam), HIWORD(lParam)-lptw->ButtonHeight, 
  928.                 SWP_NOZORDER | SWP_NOACTIVATE);
  929.             return(0);
  930.         case WM_COMMAND:
  931.             if (IsWindow(lptw->hWndText))
  932.                 SetFocus(lptw->hWndText);
  933.             SendMessage(lptw->hWndText, message, wParam, lParam); /* pass on menu commands */
  934.             return(0);
  935.         case WM_PAINT:
  936.             {
  937.             hdc = BeginPaint(hwnd, &ps);
  938.             if (lptw->ButtonHeight) {
  939.                 HBRUSH hbrush;
  940.                 GetClientRect(hwnd, &rect);
  941.                 hbrush = CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW));
  942.                 rect.bottom = lptw->ButtonHeight-1;
  943.                 FillRect(hdc, &rect, hbrush);
  944.                 DeleteBrush(hbrush);
  945.                 SelectPen(hdc, GetStockPen(BLACK_PEN));
  946.                 MoveTo(hdc, rect.left, lptw->ButtonHeight-1);
  947.                 LineTo(hdc, rect.right, lptw->ButtonHeight-1);
  948.             }
  949.             EndPaint(hwnd, &ps);
  950.             return 0;
  951.             }
  952. #if WINVER >= 0x030a
  953.         case WM_DROPFILES:
  954.             {
  955.             WORD version = LOWORD(GetVersion());
  956.             if ((LOBYTE(version)*100 + HIBYTE(version)) >= 310)
  957.                 DragFunc(lptw, (HDROP)wParam);
  958.             }
  959.             break;
  960. #endif
  961.         case WM_CREATE:
  962.             {
  963.             RECT crect, wrect;
  964.             TEXTMETRIC tm;
  965.             lptw = ((CREATESTRUCT FAR *)lParam)->lpCreateParams;
  966.             SetWindowLong(hwnd, 0, (LONG)lptw);
  967.             lptw->hWndParent = hwnd;
  968.             /* get character size */
  969.             TextMakeFont(lptw);
  970.             hdc = GetDC(hwnd);
  971.             SelectFont(hdc, lptw->hfont);
  972.             GetTextMetrics(hdc,(LPTEXTMETRIC)&tm);
  973.             lptw->CharSize.y = tm.tmHeight;
  974.             lptw->CharSize.x = tm.tmAveCharWidth;
  975.             lptw->CharAscent = tm.tmAscent;
  976.             ReleaseDC(hwnd,hdc);
  977.             GetClientRect(hwnd, &crect);
  978.             if ( (lptw->CharSize.y*lptw->ScreenSize.y < crect.bottom)
  979.               || (lptw->CharSize.x*lptw->ScreenSize.x < crect.right) ) {
  980.                 /* shrink size */
  981.                 GetWindowRect(lptw->hWndParent,&wrect);
  982.                 MoveWindow(lptw->hWndParent, wrect.left, wrect.top,
  983.                  wrect.right-wrect.left + (lptw->CharSize.x*lptw->ScreenSize.x - crect.right),
  984.                  wrect.bottom-wrect.top + (lptw->CharSize.y*lptw->ScreenSize.y+lptw->ButtonHeight - crect.bottom),
  985.                  TRUE);
  986.             }
  987.             }
  988. #if WINVER >= 0x030a
  989.             {
  990.             WORD version = LOWORD(GetVersion());
  991.             if ((LOBYTE(version)*100 + HIBYTE(version)) >= 310)
  992.                 if ( (lptw->DragPre!=(LPSTR)NULL) && (lptw->DragPost!=(LPSTR)NULL) )
  993.                     DragAcceptFiles(hwnd, TRUE);
  994.             }
  995. #endif
  996.             break;
  997.         case WM_DESTROY:
  998. #if WINVER >= 0x030a
  999.             {
  1000.             WORD version = LOWORD(GetVersion());
  1001.             if ((LOBYTE(version)*100 + HIBYTE(version)) >= 310)
  1002.                 DragAcceptFiles(hwnd, FALSE);
  1003.             }
  1004. #endif
  1005.             DeleteFont(lptw->hfont);
  1006.             lptw->hfont = 0;
  1007.             break;
  1008.         case WM_CLOSE:
  1009.             if (lptw->shutdown) {
  1010.                 FARPROC lpShutDown = lptw->shutdown;
  1011.                 (*lpShutDown)();
  1012.             }
  1013.             break;
  1014.     }
  1015.     return DefWindowProc(hwnd, message, wParam, lParam);
  1016. }
  1017.  
  1018. /* child text window */
  1019. LRESULT CALLBACK _export
  1020. WndTextProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  1021. {
  1022.     HDC hdc;
  1023.     PAINTSTRUCT ps;
  1024.     RECT rect;
  1025.     int nYinc, nXinc;
  1026.     LPTW lptw;
  1027.  
  1028.     lptw = (LPTW)GetWindowLong(hwnd, 0);
  1029.  
  1030.     switch(message) {
  1031.         case WM_SETFOCUS: 
  1032.             lptw->bFocus = TRUE;
  1033.             CreateCaret(hwnd, 0, lptw->CharSize.x, 2+lptw->CaretHeight);
  1034.             SetCaretPos(lptw->CursorPos.x*lptw->CharSize.x - lptw->ScrollPos.x,
  1035.                 lptw->CursorPos.y*lptw->CharSize.y + lptw->CharAscent
  1036.                  - lptw->CaretHeight - lptw->ScrollPos.y);
  1037.             if (lptw->bGetCh)
  1038.                 ShowCaret(hwnd);
  1039.             break;
  1040.         case WM_KILLFOCUS: 
  1041.             DestroyCaret();
  1042.             lptw->bFocus = FALSE;
  1043.             break;
  1044.         case WM_SIZE:
  1045.             lptw->ClientSize.y = HIWORD(lParam);
  1046.             lptw->ClientSize.x = LOWORD(lParam);
  1047.  
  1048.             lptw->ScrollMax.y = max(0, lptw->CharSize.y*lptw->ScreenSize.y - lptw->ClientSize.y);
  1049.             lptw->ScrollPos.y = min(lptw->ScrollPos.y, lptw->ScrollMax.y);
  1050.  
  1051.             SetScrollRange(hwnd, SB_VERT, 0, lptw->ScrollMax.y, FALSE);
  1052.             SetScrollPos(hwnd, SB_VERT, lptw->ScrollPos.y, TRUE);
  1053.  
  1054.             lptw->ScrollMax.x = max(0, lptw->CharSize.x*lptw->ScreenSize.x - lptw->ClientSize.x);
  1055.             lptw->ScrollPos.x = min(lptw->ScrollPos.x, lptw->ScrollMax.x);
  1056.  
  1057.             SetScrollRange(hwnd, SB_HORZ, 0, lptw->ScrollMax.x, FALSE);
  1058.             SetScrollPos(hwnd, SB_HORZ, lptw->ScrollPos.x, TRUE);
  1059.  
  1060.             if (lptw->bFocus && lptw->bGetCh) {
  1061.                 SetCaretPos(lptw->CursorPos.x*lptw->CharSize.x - lptw->ScrollPos.x,
  1062.                     lptw->CursorPos.y*lptw->CharSize.y + lptw->CharAscent 
  1063.                     - lptw->CaretHeight - lptw->ScrollPos.y);
  1064.                 ShowCaret(hwnd);
  1065.             }
  1066.             return(0);
  1067.         case WM_VSCROLL:
  1068.             switch(LOWORD(wParam)) {
  1069.                 case SB_TOP:
  1070.                     nYinc = -lptw->ScrollPos.y;
  1071.                     break;
  1072.                 case SB_BOTTOM:
  1073.                     nYinc = lptw->ScrollMax.y - lptw->ScrollPos.y;
  1074.                     break;
  1075.                 case SB_LINEUP:
  1076.                     nYinc = -lptw->CharSize.y;
  1077.                     break;
  1078.                 case SB_LINEDOWN:
  1079.                     nYinc = lptw->CharSize.y;
  1080.                     break;
  1081.                 case SB_PAGEUP:
  1082.                     nYinc = min(-1,-lptw->ClientSize.y);
  1083.                     break;
  1084.                 case SB_PAGEDOWN:
  1085.                     nYinc = max(1,lptw->ClientSize.y);
  1086.                     break;
  1087.                 case SB_THUMBPOSITION:
  1088.                     nYinc = LOWORD(lParam) - lptw->ScrollPos.y;
  1089.                     break;
  1090.                 default:
  1091.                     nYinc = 0;
  1092.                 }
  1093.             if ( (nYinc = max(-lptw->ScrollPos.y, 
  1094.                 min(nYinc, lptw->ScrollMax.y - lptw->ScrollPos.y)))
  1095.                 != 0 ) {
  1096.                 lptw->ScrollPos.y += nYinc;
  1097.                 ScrollWindow(hwnd,0,-nYinc,NULL,NULL);
  1098.                 SetScrollPos(hwnd,SB_VERT,lptw->ScrollPos.y,TRUE);
  1099.                 UpdateWindow(hwnd);
  1100.             }
  1101.             return(0);
  1102.         case WM_HSCROLL:
  1103.             switch(LOWORD(wParam)) {
  1104.                 case SB_LINEUP:
  1105.                     nXinc = -lptw->CharSize.x;
  1106.                     break;
  1107.                 case SB_LINEDOWN:
  1108.                     nXinc = lptw->CharSize.x;
  1109.                     break;
  1110.                 case SB_PAGEUP:
  1111.                     nXinc = min(-1,-lptw->ClientSize.x);
  1112.                     break;
  1113.                 case SB_PAGEDOWN:
  1114.                     nXinc = max(1,lptw->ClientSize.x);
  1115.                     break;
  1116.                 case SB_THUMBPOSITION:
  1117.                     nXinc = LOWORD(lParam) - lptw->ScrollPos.x;
  1118.                     break;
  1119.                 default:
  1120.                     nXinc = 0;
  1121.                 }
  1122.             if ( (nXinc = max(-lptw->ScrollPos.x, 
  1123.                 min(nXinc, lptw->ScrollMax.x - lptw->ScrollPos.x)))
  1124.                 != 0 ) {
  1125.                 lptw->ScrollPos.x += nXinc;
  1126.                 ScrollWindow(hwnd,-nXinc,0,NULL,NULL);
  1127.                 SetScrollPos(hwnd,SB_HORZ,lptw->ScrollPos.x,TRUE);
  1128.                 UpdateWindow(hwnd);
  1129.             }
  1130.             return(0);
  1131.         case WM_KEYDOWN:
  1132.             if (GetKeyState(VK_SHIFT) < 0) {
  1133.               switch(wParam) {
  1134.                 case VK_HOME:
  1135.                     SendMessage(hwnd, WM_VSCROLL, SB_TOP, (LPARAM)0);
  1136.                     break;
  1137.                 case VK_END:
  1138.                     SendMessage(hwnd, WM_VSCROLL, SB_BOTTOM, (LPARAM)0);
  1139.                     break;
  1140.                 case VK_PRIOR:
  1141.                     SendMessage(hwnd, WM_VSCROLL, SB_PAGEUP, (LPARAM)0);
  1142.                     break;
  1143.                 case VK_NEXT:
  1144.                     SendMessage(hwnd, WM_VSCROLL, SB_PAGEDOWN, (LPARAM)0);
  1145.                     break;
  1146.                 case VK_UP:
  1147.                     SendMessage(hwnd, WM_VSCROLL, SB_LINEUP, (LPARAM)0);
  1148.                     break;
  1149.                 case VK_DOWN:
  1150.                     SendMessage(hwnd, WM_VSCROLL, SB_LINEDOWN, (LPARAM)0);
  1151.                     break;
  1152.                 case VK_LEFT:
  1153.                     SendMessage(hwnd, WM_HSCROLL, SB_LINEUP, (LPARAM)0);
  1154.                     break;
  1155.                 case VK_RIGHT:
  1156.                     SendMessage(hwnd, WM_HSCROLL, SB_LINEDOWN, (LPARAM)0);
  1157.                     break;
  1158.               }
  1159.             }
  1160.             else {
  1161.               switch(wParam) {
  1162.                 case VK_HOME:
  1163.                 case VK_END:
  1164.                 case VK_PRIOR:
  1165.                 case VK_NEXT:
  1166.                 case VK_UP:
  1167.                 case VK_DOWN:
  1168.                 case VK_LEFT:
  1169.                 case VK_RIGHT:
  1170.                 case VK_DELETE:
  1171.                 { /* store key in circular buffer */
  1172.                 long count;
  1173.                     count = lptw->KeyBufIn - lptw->KeyBufOut;
  1174.                     if (count < 0) count += lptw->KeyBufSize;
  1175.                     if (count < lptw->KeyBufSize-2) {
  1176.                         *lptw->KeyBufIn++ = 0;
  1177.                         if (lptw->KeyBufIn - lptw->KeyBuf >= lptw->KeyBufSize)
  1178.                             lptw->KeyBufIn = lptw->KeyBuf;    /* wrap around */
  1179.                         *lptw->KeyBufIn++ = HIWORD(lParam) & 0xff;
  1180.                         if (lptw->KeyBufIn - lptw->KeyBuf >= lptw->KeyBufSize)
  1181.                             lptw->KeyBufIn = lptw->KeyBuf;    /* wrap around */
  1182.                     }
  1183.                 }
  1184.               }
  1185.             }
  1186.             break;
  1187.         case WM_RBUTTONDOWN:
  1188.             {
  1189.             POINT pt;
  1190.             pt.x = LOWORD(lParam);
  1191.             pt.y = HIWORD(lParam);
  1192.             ClientToScreen(hwnd,&pt);
  1193.             TrackPopupMenu(lptw->hPopMenu, TPM_LEFTALIGN, 
  1194.                 pt.x, pt.y, 0, hwnd, NULL);
  1195.             }
  1196.             return(0);
  1197.         case WM_LBUTTONDOWN:
  1198.             { /* start marking text */
  1199.             POINT pt;
  1200.             pt.x = LOWORD(lParam);
  1201.             pt.y = HIWORD(lParam);
  1202.             pt.x = (pt.x + lptw->ScrollPos.x)/lptw->CharSize.x;
  1203.             pt.y = (pt.y + lptw->ScrollPos.y)/lptw->CharSize.y;
  1204.             ClearMark(lptw, pt);
  1205.             }
  1206.             SetCapture(hwnd);    /* track the mouse */
  1207.             lptw->Marking = TRUE;
  1208.             break;
  1209.         case WM_LBUTTONUP:
  1210.             { /* finish marking text */
  1211.             /* ensure begin mark is before end mark */
  1212.             ReleaseCapture();
  1213.             lptw->Marking = FALSE;
  1214.             if ((lptw->ScreenSize.x*lptw->MarkBegin.y + lptw->MarkBegin.x) >
  1215.                 (lptw->ScreenSize.x*lptw->MarkEnd.y   + lptw->MarkEnd.x)) {
  1216.                 POINT tmp;
  1217.                 tmp.x = lptw->MarkBegin.x;
  1218.                 tmp.y = lptw->MarkBegin.y;
  1219.                 lptw->MarkBegin.x = lptw->MarkEnd.x;
  1220.                 lptw->MarkBegin.y = lptw->MarkEnd.y;
  1221.                 lptw->MarkEnd.x   = tmp.x;
  1222.                 lptw->MarkEnd.y   = tmp.y;
  1223.             }
  1224.             }
  1225.             break;
  1226.         case WM_MOUSEMOVE:
  1227.             if ( (wParam & MK_LBUTTON) && lptw->Marking ) {
  1228.             RECT rect;
  1229.             POINT pt;
  1230.             pt.x = LOWORD(lParam);
  1231.             pt.y = HIWORD(lParam);
  1232.             GetClientRect(hwnd, &rect);
  1233.             if (PtInRect(&rect, pt)) {
  1234.                 pt.x = (pt.x + lptw->ScrollPos.x)/lptw->CharSize.x;
  1235.                 pt.y = (pt.y + lptw->ScrollPos.y)/lptw->CharSize.y;
  1236.                 UpdateMark(lptw, pt);
  1237.             }
  1238.             else {
  1239.               int nXinc;
  1240.               int nYinc;
  1241.               do {
  1242.                 nXinc = 0;
  1243.                 nYinc = 0;
  1244.                 if (pt.x > rect.right) {
  1245.                     nXinc = lptw->CharSize.x * 4;
  1246.                     pt.x = (rect.right + lptw->ScrollPos.x)/lptw->CharSize.x + 2;
  1247.                 }
  1248.                 else if (pt.x < rect.left) {
  1249.                     nXinc = -lptw->CharSize.x * 4;
  1250.                     pt.x = (rect.left + lptw->ScrollPos.x)/lptw->CharSize.x - 2;
  1251.                 }
  1252.                 else
  1253.                     pt.x = (pt.x + lptw->ScrollPos.x)/lptw->CharSize.x;
  1254.                 if (pt.y > rect.bottom) {
  1255.                     nYinc = lptw->CharSize.y;
  1256.                     pt.y = (rect.bottom + lptw->ScrollPos.y)/lptw->CharSize.y + 1;
  1257.                 }
  1258.                 else if (pt.y < rect.top) {
  1259.                     nYinc = -lptw->CharSize.y;
  1260.                     pt.y = (rect.top + lptw->ScrollPos.y)/lptw->CharSize.y - 1;
  1261.                 }
  1262.                 else
  1263.                     pt.y = (pt.y + lptw->ScrollPos.y)/lptw->CharSize.y;
  1264.                 LimitMark(lptw, &pt);
  1265.                 nXinc = max(nXinc, -lptw->ScrollPos.x);
  1266.                 nYinc = max(nYinc, -lptw->ScrollPos.y);
  1267.                 nYinc = min(nYinc, lptw->ScrollMax.y - lptw->ScrollPos.y);
  1268.                 nXinc = min(nXinc, lptw->ScrollMax.x - lptw->ScrollPos.x);
  1269.                 if (nYinc || nXinc) {
  1270.                     lptw->ScrollPos.y += nYinc;
  1271.                     lptw->ScrollPos.x += nXinc;
  1272.                     ScrollWindow(lptw->hWndText,-nXinc,-nYinc,NULL,NULL);
  1273.                     SetScrollPos(lptw->hWndText,SB_VERT,lptw->ScrollPos.y,TRUE);
  1274.                     SetScrollPos(lptw->hWndText,SB_HORZ,lptw->ScrollPos.x,TRUE);
  1275.                     UpdateWindow(lptw->hWndText);
  1276.                 }
  1277.                 UpdateMark(lptw, pt);
  1278.                 GetCursorPos(&pt);
  1279.                 ScreenToClient(hwnd, &pt);
  1280.               }
  1281.               while( (nYinc || nXinc) && !PtInRect(&rect, pt) &&
  1282.                 (GetAsyncKeyState(VK_LBUTTON) < 0) );
  1283.             }
  1284.             }
  1285.             break;
  1286.         case WM_CHAR:
  1287.             { /* store key in circular buffer */
  1288.             long count;
  1289.                 count = lptw->KeyBufIn - lptw->KeyBufOut;
  1290.                 if (count < 0) count += lptw->KeyBufSize;
  1291.                 if (count < lptw->KeyBufSize-1) {
  1292.                     *lptw->KeyBufIn++ = wParam;
  1293.                     if (lptw->KeyBufIn - lptw->KeyBuf >= lptw->KeyBufSize)
  1294.                         lptw->KeyBufIn = lptw->KeyBuf;    /* wrap around */
  1295.                 }
  1296.             }
  1297.             return(0);
  1298.         case WM_COMMAND:
  1299.             if (LOWORD(wParam) < NUMMENU)
  1300.                 SendMacro(lptw, LOWORD(wParam));
  1301.             else
  1302.             switch(LOWORD(wParam))
  1303.             {
  1304.                 case M_COPY_CLIP:
  1305.                     TextCopyClip(lptw);
  1306.                     return 0;
  1307.                 case M_PASTE:
  1308.                     {
  1309.                     HGLOBAL hGMem;
  1310.                     BYTE FAR *cbuf;
  1311.                     TEXTMETRIC tm;
  1312.                     UINT type;
  1313.                     /* find out what type to get from clipboard */
  1314.                     hdc = GetDC(hwnd);
  1315.                     SelectFont(hdc, lptw->hfont);
  1316.                     GetTextMetrics(hdc,(TEXTMETRIC FAR *)&tm);
  1317.                     if (tm.tmCharSet == OEM_CHARSET)
  1318.                         type = CF_OEMTEXT;
  1319.                     else
  1320.                         type = CF_TEXT;
  1321.                     ReleaseDC(lptw->hWndText, hdc);
  1322.                     /* now get it from clipboard */
  1323.                     OpenClipboard(hwnd);
  1324.                     hGMem = GetClipboardData(type);
  1325.                     if (hGMem) {
  1326.                         cbuf = (BYTE FAR *) GlobalLock(hGMem);
  1327.                         while (*cbuf) {
  1328.                             if (*cbuf != '\n')
  1329.                                 SendMessage(lptw->hWndText,WM_CHAR,*cbuf,1L);
  1330.                             cbuf++;
  1331.                         }
  1332.                         GlobalUnlock(hGMem);
  1333.                     }
  1334.                     CloseClipboard();
  1335.                     return 0;
  1336.                     }
  1337.                 case M_CHOOSE_FONT:
  1338.                     TextSelectFont(lptw);
  1339.                     return 0;
  1340.                 case M_WRITEINI:
  1341.                     WriteTextIni(lptw);
  1342.                     return 0;
  1343.                 case M_ABOUT:
  1344.                     AboutBox(hwnd,lptw->AboutText);
  1345.                     return 0;
  1346.             }
  1347.             return(0);
  1348.         case WM_PAINT:
  1349.             {
  1350.             POINT source, width, dest;
  1351.             POINT MarkBegin, MarkEnd;
  1352.             hdc = BeginPaint(hwnd, &ps);
  1353.             SelectFont(hdc, lptw->hfont);
  1354.             SetMapMode(hdc, MM_TEXT);
  1355.             SetBkMode(hdc,OPAQUE);
  1356.             GetClientRect(hwnd, &rect);
  1357.             source.x = (rect.left + lptw->ScrollPos.x) / lptw->CharSize.x;        /* source */
  1358.             source.y = (rect.top + lptw->ScrollPos.y) / lptw->CharSize.y;
  1359.             dest.x = source.x * lptw->CharSize.x - lptw->ScrollPos.x;                 /* destination */
  1360.             dest.y = source.y * lptw->CharSize.y - lptw->ScrollPos.y;
  1361.             width.x = ((rect.right  + lptw->ScrollPos.x + lptw->CharSize.x - 1) / lptw->CharSize.x) - source.x; /* width */
  1362.             width.y = ((rect.bottom + lptw->ScrollPos.y + lptw->CharSize.y - 1) / lptw->CharSize.y) - source.y;
  1363.             if (source.x < 0)
  1364.                 source.x = 0;
  1365.             if (source.y < 0)
  1366.                 source.y = 0;
  1367.             if (source.x+width.x > lptw->ScreenSize.x)
  1368.                 width.x = lptw->ScreenSize.x - source.x;
  1369.             if (source.y+width.y > lptw->ScreenSize.y)
  1370.                 width.y = lptw->ScreenSize.y - source.y;
  1371.             /* ensure begin mark is before end mark */
  1372.             if ((lptw->ScreenSize.x*lptw->MarkBegin.y + lptw->MarkBegin.x) >
  1373.                 (lptw->ScreenSize.x*lptw->MarkEnd.y   + lptw->MarkEnd.x)) {
  1374.                 MarkBegin.x = lptw->MarkEnd.x;
  1375.                 MarkBegin.y = lptw->MarkEnd.y;
  1376.                 MarkEnd.x   = lptw->MarkBegin.x;
  1377.                 MarkEnd.y   = lptw->MarkBegin.y;
  1378.             }
  1379.             else {
  1380.                 MarkBegin.x = lptw->MarkBegin.x;
  1381.                 MarkBegin.y = lptw->MarkBegin.y;
  1382.                 MarkEnd.x   = lptw->MarkEnd.x;
  1383.                 MarkEnd.y   = lptw->MarkEnd.y;
  1384.             }
  1385.             /* for each line */
  1386.             while (width.y>0) {
  1387.                 if ( (source.y >= MarkBegin.y) && (source.y <= MarkEnd.y) ) {
  1388.                     int start, end;
  1389.                     int count, offset;
  1390.                     if (source.y == MarkBegin.y)
  1391.                         start = MarkBegin.x;
  1392.                     else
  1393.                         start = 0;
  1394.                     if (source.y == MarkEnd.y)
  1395.                         end = MarkEnd.x;
  1396.                     else
  1397.                         end = lptw->ScreenSize.x;
  1398.                     /* do stuff before marked text */
  1399.                     offset = 0;
  1400.                     count = start - source.x;
  1401.                     if (count > 0)
  1402.                       DoLine(lptw, hdc, dest.x, dest.y, 
  1403.                         source.y*lptw->ScreenSize.x + source.x, count);
  1404.                     /* then the marked text */
  1405.                     offset += count;
  1406.                     count = end - start;
  1407.                     if ((count > 0) && (offset < width.x)){
  1408.                       SetTextColor(hdc, MARKFORE);
  1409.                       SetBkColor(hdc, MARKBACK);
  1410.                       TextOut(hdc, dest.x + lptw->CharSize.x*offset, dest.y, 
  1411.                         (LPSTR)(lptw->ScreenBuffer + source.y*lptw->ScreenSize.x 
  1412.                         + source.x + offset), count);
  1413.                     }
  1414.                     /* then stuff after marked text */
  1415.                     offset += count;
  1416.                     count = width.x + source.x - end;
  1417.                     if ((count > 0) && (offset < width.x))
  1418.                       DoLine(lptw, hdc, dest.x + lptw->CharSize.x*offset, dest.y, 
  1419.                         source.y*lptw->ScreenSize.x + source.x + offset, count);
  1420.                 }
  1421.                 else {
  1422.                     DoLine(lptw, hdc, dest.x, dest.y, 
  1423.                         source.y*lptw->ScreenSize.x + source.x, width.x);
  1424.                 }
  1425.                 dest.y += lptw->CharSize.y;
  1426.                 source.y++;
  1427.                 width.y--;
  1428.             }
  1429.             EndPaint(hwnd, &ps);
  1430.             return 0;
  1431.             }
  1432.         case WM_CREATE:
  1433.             lptw = ((CREATESTRUCT FAR *)lParam)->lpCreateParams;
  1434.             SetWindowLong(hwnd, 0, (LONG)lptw);
  1435.             lptw->hWndText = hwnd;
  1436.             break;
  1437.         case WM_DESTROY:
  1438.             break;
  1439.     }
  1440.     return DefWindowProc(hwnd, message, wParam, lParam);
  1441. }
  1442.  
  1443.  
  1444. /* ================================== */
  1445. /* replacement stdio routines */
  1446.  
  1447. /* TRUE if key hit, FALSE if no key */
  1448. int WDPROC
  1449. TextKBHit(LPTW lptw)
  1450. {
  1451.     return (lptw->KeyBufIn != lptw->KeyBufOut);
  1452. }
  1453.  
  1454. /* get character from keyboard, no echo */
  1455. /* need to add extended codes */
  1456. int WDPROC
  1457. TextGetCh(LPTW lptw)
  1458. {
  1459.     int ch;
  1460.     TextToCursor(lptw);
  1461.     lptw->bGetCh = TRUE;
  1462.     if (lptw->bFocus) {
  1463.         SetCaretPos(lptw->CursorPos.x*lptw->CharSize.x - lptw->ScrollPos.x,
  1464.             lptw->CursorPos.y*lptw->CharSize.y + lptw->CharAscent 
  1465.             - lptw->CaretHeight - lptw->ScrollPos.y);
  1466.         ShowCaret(lptw->hWndText);
  1467.     }
  1468.     do {
  1469.         TextMessage();
  1470.     } while (!TextKBHit(lptw));
  1471.     ch = *lptw->KeyBufOut++;
  1472.     if (ch=='\r')
  1473.         ch = '\n';
  1474.     if (lptw->KeyBufOut - lptw->KeyBuf >= lptw->KeyBufSize)
  1475.         lptw->KeyBufOut = lptw->KeyBuf;    /* wrap around */
  1476.     if (lptw->bFocus)
  1477.         HideCaret(lptw->hWndText);
  1478.     lptw->bGetCh = FALSE;
  1479.     return ch;
  1480. }
  1481.  
  1482. /* get character from keyboard, with echo */
  1483. int WDPROC
  1484. TextGetChE(LPTW lptw)
  1485. {
  1486. int ch;
  1487.     ch = TextGetCh(lptw);
  1488.     TextPutCh(lptw, (BYTE)ch);
  1489.     return ch;
  1490. }
  1491.  
  1492. LPSTR WDPROC
  1493. TextGetS(LPTW lptw, LPSTR str, unsigned int size)
  1494. {
  1495.     LPSTR next = str;
  1496.     while (--size>0) {
  1497.         switch(*next = TextGetChE(lptw)) {
  1498.             case EOF:
  1499.                 *next = NULL;
  1500.                 if (next == str) return (char *)NULL;
  1501.                 return str;
  1502.             case '\n':
  1503.                 *(next+1) = NULL;
  1504.                 return str;
  1505.             case 0x08:
  1506.             case 0x7f:
  1507.                 if (next > str)
  1508.                     --next;
  1509.                 break;
  1510.             default:
  1511.                 ++next;
  1512.         }
  1513.     }
  1514.     *next = NULL;
  1515.     return str;
  1516. }
  1517.  
  1518. int WDPROC
  1519. TextPutS(LPTW lptw, LPSTR str)
  1520. {
  1521.     TextPutStr(lptw, str);
  1522.     return str[_fstrlen(str)-1];
  1523. }
  1524.  
  1525. /* ================================== */
  1526. /* routines added for elvis */
  1527.  
  1528. void WDPROC
  1529. TextGotoXY(LPTW lptw, int x, int y)
  1530. {
  1531.     lptw->CursorPos.x = x;
  1532.     lptw->CursorPos.y = y;
  1533. }
  1534.  
  1535. int  WDPROC
  1536. TextWhereX(LPTW lptw)
  1537. {
  1538.     return lptw->CursorPos.x;
  1539. }
  1540.  
  1541. int  WDPROC
  1542. TextWhereY(LPTW lptw)
  1543. {
  1544.     return lptw->CursorPos.y;
  1545. }
  1546.  
  1547. void WDPROC
  1548. TextCursorHeight(LPTW lptw, int height)
  1549. {
  1550.     lptw->CaretHeight = height;
  1551.     if (lptw->bFocus)
  1552.         CreateCaret(lptw->hWndText, 0, lptw->CharSize.x, 2+lptw->CaretHeight);
  1553. }
  1554.  
  1555. void WDPROC
  1556. TextClearEOL(LPTW lptw)
  1557. {
  1558. HDC hdc;
  1559. int xpos, ypos;
  1560. int from, len;
  1561. POINT pt;
  1562.     pt.x = pt.y = 0;
  1563.     ClearMark(lptw, pt);
  1564.     from = lptw->CursorPos.y*lptw->ScreenSize.x + lptw->CursorPos.x;
  1565.     len = lptw->ScreenSize.x-lptw->CursorPos.x;
  1566.     _fmemset(lptw->ScreenBuffer + from, ' ', len);
  1567.     _fmemset(lptw->AttrBuffer + from, NOTEXT, len);
  1568.     xpos = lptw->CursorPos.x*lptw->CharSize.x - lptw->ScrollPos.x;
  1569.     ypos = lptw->CursorPos.y*lptw->CharSize.y - lptw->ScrollPos.y;
  1570.     hdc = GetDC(lptw->hWndText);
  1571.     SetTextColor(hdc, TextFore(lptw->Attr));
  1572.     SetBkColor(hdc, TextBack(lptw->Attr));
  1573.     SelectFont(hdc, (lptw->hfont));
  1574.     TextOut(hdc,xpos,ypos,
  1575.         (LPSTR)(lptw->ScreenBuffer + lptw->CursorPos.y*lptw->ScreenSize.x + 
  1576.         lptw->CursorPos.x), lptw->ScreenSize.x-lptw->CursorPos.x);
  1577.     (void)ReleaseDC(lptw->hWndText,hdc);
  1578. }
  1579.  
  1580. void WDPROC
  1581. TextClearEOS(LPTW lptw)
  1582. {
  1583. RECT rect;
  1584. int from, len;
  1585. POINT pt;
  1586.     pt.x = pt.y = 0;
  1587.     ClearMark(lptw, pt);
  1588.     from = lptw->CursorPos.y*lptw->ScreenSize.x + lptw->CursorPos.x;
  1589.     len = lptw->ScreenSize.x-lptw->CursorPos.x + 
  1590.             (lptw->ScreenSize.y-lptw->CursorPos.y-1)*lptw->ScreenSize.x;
  1591.     _fmemset(lptw->ScreenBuffer + from, ' ', len);
  1592.     _fmemset(lptw->AttrBuffer + from, NOTEXT, len);
  1593.     GetClientRect(lptw->hWndText, (LPRECT) &rect);
  1594.     InvalidateRect(lptw->hWndText, (LPRECT) &rect, 1);
  1595.     UpdateWindow(lptw->hWndText);
  1596. }
  1597.  
  1598. void WDPROC
  1599. TextInsertLine(LPTW lptw)
  1600. {
  1601. RECT rect;
  1602. int from, to, len;
  1603. POINT pt;
  1604.     pt.x = pt.y = 0;
  1605.     ClearMark(lptw, pt);
  1606.     from = lptw->CursorPos.y*lptw->ScreenSize.x,
  1607.     to = (lptw->CursorPos.y+1)*lptw->ScreenSize.x;
  1608.     len = (lptw->ScreenSize.y-lptw->CursorPos.y-1)*lptw->ScreenSize.x;
  1609.     _fmemmove(lptw->ScreenBuffer + to, lptw->ScreenBuffer + from, len);
  1610.     _fmemmove(lptw->AttrBuffer + to, lptw->AttrBuffer + from, len);
  1611.     _fmemset(lptw->ScreenBuffer + from, ' ', lptw->ScreenSize.x);
  1612.     _fmemset(lptw->AttrBuffer + from, NOTEXT, lptw->ScreenSize.x);
  1613.     GetClientRect(lptw->hWndText, (LPRECT) &rect);
  1614.     InvalidateRect(lptw->hWndText, (LPRECT) &rect, 1);
  1615.     UpdateWindow(lptw->hWndText);
  1616.     if (lptw->CursorFlag)
  1617.         TextToCursor(lptw);
  1618. }
  1619.  
  1620. void WDPROC
  1621. TextDeleteLine(LPTW lptw)
  1622. {
  1623. RECT rect;
  1624. int from, to, len;
  1625. POINT pt;
  1626.     pt.x = pt.y = 0;
  1627.     ClearMark(lptw, pt);
  1628.     to = lptw->CursorPos.y*lptw->ScreenSize.x,
  1629.     from = (lptw->CursorPos.y+1)*lptw->ScreenSize.x;
  1630.     len = (lptw->ScreenSize.y-lptw->CursorPos.y-1)*lptw->ScreenSize.x;
  1631.     _fmemmove(lptw->ScreenBuffer + to, lptw->ScreenBuffer + from, len);
  1632.     _fmemmove(lptw->AttrBuffer + to, lptw->AttrBuffer + from, len);
  1633.     from = lptw->ScreenSize.x*(lptw->ScreenSize.y -1);
  1634.     _fmemset(lptw->ScreenBuffer + from, ' ', lptw->ScreenSize.x);
  1635.     _fmemset(lptw->AttrBuffer + from, NOTEXT, lptw->ScreenSize.x);
  1636.     GetClientRect(lptw->hWndText, (LPRECT) &rect);
  1637.     InvalidateRect(lptw->hWndText, (LPRECT) &rect, 1);
  1638.     UpdateWindow(lptw->hWndText);
  1639.     if (lptw->CursorFlag)
  1640.         TextToCursor(lptw);
  1641. }
  1642.  
  1643. void WDPROC
  1644. TextScrollReverse(LPTW lptw)
  1645. {
  1646. RECT rect;
  1647. int len = lptw->ScreenSize.x * (lptw->ScreenSize.y - 1); 
  1648.     _fmemmove(lptw->ScreenBuffer+lptw->ScreenSize.x, lptw->ScreenBuffer, len);
  1649.     _fmemset(lptw->ScreenBuffer, ' ', lptw->ScreenSize.x);
  1650.     _fmemmove(lptw->AttrBuffer+lptw->ScreenSize.x, lptw->AttrBuffer, len);
  1651.     _fmemset(lptw->AttrBuffer, NOTEXT, lptw->ScreenSize.x);
  1652.     if (lptw->CursorPos.y)
  1653.         lptw->CursorPos.y--;
  1654.     ScrollWindow(lptw->hWndText,0,+lptw->CharSize.y,NULL,NULL);
  1655.     GetClientRect(lptw->hWndText, (LPRECT) &rect);
  1656.     rect.top = lptw->ScreenSize.y*lptw->CharSize.y;
  1657.     if (rect.top < rect.bottom)
  1658.         InvalidateRect(lptw->hWndText, (LPRECT) &rect, 1);
  1659.     lptw->MarkBegin.y++;
  1660.     lptw->MarkEnd.y++;
  1661.     LimitMark(lptw, &lptw->MarkBegin);
  1662.     LimitMark(lptw, &lptw->MarkEnd);
  1663.     UpdateWindow(lptw->hWndText);
  1664. }
  1665.  
  1666. void WDPROC 
  1667. TextAttr(LPTW lptw, BYTE attr)
  1668. {
  1669.     lptw->Attr = attr;
  1670. }
  1671.  
  1672. /* About Box */
  1673. BOOL CALLBACK _export
  1674. AboutDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam)
  1675. {
  1676.     switch (wMsg) {
  1677.         case WM_INITDIALOG:
  1678.             {
  1679.             char buf[80];
  1680.             GetWindowText(GetParent(hDlg),buf,80);
  1681.             SetDlgItemText(hDlg, AB_TEXT1, buf);
  1682.             SetDlgItemText(hDlg, AB_TEXT2, (LPSTR)lParam);
  1683. #ifdef __DLL__
  1684.             wsprintf(buf,"WGNUPLOT.DLL Version %s",(LPSTR)WGNUPLOTVERSION);
  1685.             SetDlgItemText(hDlg, AB_TEXT3, buf);
  1686. #endif
  1687.             }
  1688.             return TRUE;
  1689.         case WM_DRAWITEM:
  1690.             {
  1691.             LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
  1692. #ifdef WIN32
  1693.             DrawIcon(lpdis->hDC, 0, 0, (HICON)GetClassLong(GetParent(hDlg), GCL_HICON));
  1694. #else
  1695.             DrawIcon(lpdis->hDC, 0, 0, (HICON)GetClassWord(GetParent(hDlg), GCW_HICON));
  1696. #endif
  1697.             }
  1698.             return FALSE;
  1699.         case WM_COMMAND:
  1700.             switch (LOWORD(wParam)) {
  1701.                 case IDCANCEL:
  1702.                 case IDOK:
  1703.                     EndDialog(hDlg, LOWORD(wParam));
  1704.                     return TRUE;
  1705.             }
  1706.             break;
  1707.     }
  1708.     return FALSE;
  1709. }
  1710.  
  1711.  
  1712. void WDPROC
  1713. AboutBox(HWND hwnd, LPSTR str)
  1714. {
  1715. DLGPROC lpfnAboutDlgProc;
  1716. #ifdef __DLL__
  1717.     lpfnAboutDlgProc = (DLGPROC)GetProcAddress(hdllInstance, "AboutDlgProc");
  1718. #else
  1719.     lpfnAboutDlgProc = (DLGPROC)MakeProcInstance((FARPROC)AboutDlgProc, hdllInstance);
  1720. #endif
  1721.     DialogBoxParam(hdllInstance,"AboutDlgBox",hwnd,lpfnAboutDlgProc,(LPARAM)str);
  1722.     EnableWindow(hwnd,TRUE);
  1723. #ifndef __DLL__
  1724.     FreeProcInstance((FARPROC)lpfnAboutDlgProc);
  1725. #endif
  1726. }
  1727.