home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / win100.zip / winkpx.c < prev    next >
C/C++ Source or Header  |  1991-10-20  |  19KB  |  687 lines

  1. /*
  2.  * Windows Kermit
  3.  * 
  4.  * Written by William S. Hall
  5.  *          3665 Benton Street, #66
  6.  *          Santa Clara, CA 95051
  7.  *
  8.  * protocol function support module
  9.  */
  10.  
  11. #define NOKANJI
  12. #define NOATOM
  13. #define NOMINMAX
  14. #include <windows.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17.  
  18. #include "winasc.h"
  19. #include "winkpr.h"
  20. #include "winkpf.h"
  21.  
  22. extern int cid;
  23.  
  24. struct DisplayWnd {
  25.     HWND hWnd;
  26.     HANDLE hVidBuffer;
  27.     BYTE *pVidBuffer;
  28.     short Width, Height;
  29.     short CharWidth, CharHeight;
  30.     short Xpos, Ypos;
  31.     short MaxLines, MaxCols;
  32.     short MaxLineLength;
  33.     short oCurrentLine;
  34.     short oVidLastLine;
  35.     short CurrLineOffset;
  36. };
  37.  
  38. typedef struct DisplayWnd *PDISPLAYWND;
  39. static struct DisplayWnd DWnd;
  40.  
  41. /* local functions */
  42. static void near ResetFTParams(HWND hWnd, int mode);
  43. BOOL FAR PASCAL krmShowChildren(HWND hWnd, LONG lParam);
  44. static void NEAR krmGrayMenus(HWND hWnd, int mode, int style);
  45. static void NEAR krmShowResult(HWND hWnd, int mode);
  46. static void NEAR DoMCR(PDISPLAYWND pDWnd);
  47. static void NEAR DoMLF(PDISPLAYWND pDWnd);
  48. static void NEAR DoMBS(PDISPLAYWND pDWnd);
  49. static void NEAR DoMTab(PDISPLAYWND pDWnd);
  50. static void NEAR krmLongReplyUpdate(HDC hDC);
  51. static void NEAR krmShowPackets(HWND hWnd, HDC hDC);
  52.  
  53. /* show packets when iconic */
  54. static void NEAR krmShowPackets(HWND hWnd, HDC hDC)
  55. {
  56.  
  57.     char numstr[10];
  58.     register char *ptr;
  59.     register int num;
  60.     RECT rcPaint;
  61.  
  62.     GetClientRect(hWnd, (LPRECT)&rcPaint);
  63.     
  64.     num = unchar(sndpkt.pktbuf[2]);
  65.     numstr[0] = sndpkt.pktbuf[3];
  66.     numstr[1] = numstr[6] = '-';
  67.  
  68.     if (num < 10) {
  69.         numstr[2] = '0';
  70.         ptr = numstr + 3;
  71.     }
  72.     else
  73.         ptr = numstr + 2;
  74.     itoa(num, ptr, 10);
  75.  
  76.     numstr[4] = SP;
  77.  
  78.     numstr[5] = rcvpkt.type;
  79.     if ((num = rcvpkt.num) < 10) {
  80.         numstr[7] = '0';
  81.     ptr = numstr + 8;
  82.     }
  83.     else
  84.     ptr = numstr + 7;
  85.     itoa(num, ptr, 10);
  86.  
  87.     DrawText(hDC, (LPSTR)numstr,-1,(LPRECT)&rcPaint,
  88.                  DT_LEFT | DT_NOCLIP | DT_WORDBREAK | DT_EXTERNALLEADING);
  89. }
  90.  
  91. /* show large responses or data when iconic */
  92. void krmShowTransferData(HWND hWnd, HDC hDC, BOOL iconic)
  93. {
  94.  
  95.     if (iconic)
  96.      krmShowPackets(hWnd, hDC);
  97.     else
  98.         if (DWnd.hVidBuffer)
  99.         krmLongReplyUpdate(hDC);
  100. }
  101.  
  102. /* show long responses */
  103. static void NEAR krmLongReplyUpdate(HDC hDC)
  104. {
  105.     
  106.     BYTE *pBuf = DWnd.pVidBuffer;        /* top of buffer */
  107.     BYTE *pEnd = pBuf + DWnd.oVidLastLine;    /* last line in buffer */
  108.     register BYTE *lineptr = pBuf + DWnd.oCurrentLine; /* current line in buf */
  109.     short base = DWnd.Ypos;    /* starting screen position of current line */
  110.     short lines = DWnd.MaxLines;    /* number of lines in tty window */
  111.     short length = DWnd.MaxLineLength;    /* byte increment to next line */
  112.     short cheight = DWnd.CharHeight;
  113.     register int i;
  114.  
  115.     SetBkMode(hDC, TRANSPARENT);
  116.     SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
  117.  
  118.   /* loop through the lines, starting with the current one */
  119.     for (i = 0; i < lines; i++) {
  120.         TextOut(hDC, 0, base, lineptr, strlen(lineptr));
  121.   /* update the line pointer */
  122.     if ((lineptr -= length) < pBuf)
  123.         lineptr = pEnd;
  124.     base -= cheight;    /* move the position of the next line */
  125.     }
  126. }
  127.  
  128. /* process Kermit menu items */
  129. void krmProcessKermitMenu(HWND hWnd, WORD menuitem)
  130. {
  131.  
  132.     HANDLE hInstance = (HANDLE)GetWindowWord(hWnd, GWW_HINSTANCE);
  133.     FARPROC fp;
  134.     LPSTR boxstr;
  135.  
  136.     switch (menuitem) {
  137.  
  138.     case IDM_MXPARAMS:
  139.         fp = MakeProcInstance((FARPROC)SetMiscParams, hInstance);
  140.         DialogBox(hInstance, MAKEINTRESOURCE(DT_KRM_MXPARAMS),hWnd,fp);
  141.         FreeProcInstance(fp);
  142.         break;
  143.  
  144.     case IDM_CANCELFILE:
  145.         Kermit.fileabort = TRUE;
  146.         break;
  147.  
  148.     case IDM_CANCELBATCH:
  149.         Kermit.batchabort = TRUE;
  150.         break;
  151.  
  152.     case IDM_ERRORCANCEL:
  153.         Kermit.protocolabort = TRUE;
  154.         break;
  155.  
  156.     case IDM_CANCELPROTOCOL:
  157.         clsif(); clsof(TRUE);
  158.         ResetFTParams(hWnd, krmState);
  159.         krmState = 0;
  160.         break;
  161.  
  162.     case IDM_KRM_RECEIVE:
  163.         Kermit.sstate = 'v';
  164.         krmState = menuitem;        
  165.         break;
  166.  
  167.     case IDM_KRM_FINISH:
  168.     case IDM_KRM_LOGOUT:
  169.     case IDM_KRM_BYE:
  170.         Kermit.sstate = 'g';
  171.         krmState = menuitem;
  172.         break;
  173.  
  174.     case IDM_KRM_GET:
  175.         Kermit.remotecmd = 'R';
  176.         Kermit.ids_title = IDS_KRM_GETFILES;
  177.         Kermit.nullstrOK = FALSE;
  178.         Kermit.sstate = 'r';
  179.         boxstr = MAKEINTRESOURCE(DT_KRM_GETFILE);
  180.         fp = MakeProcInstance((FARPROC)GetFileList, hInstance);
  181.         if (DialogBox(hInstance, boxstr, hWnd, fp))
  182.         krmState = menuitem;
  183.         FreeProcInstance(fp);
  184.         break;
  185.  
  186.     case IDM_KRM_REMOTEHOST:
  187.         Kermit.remotecmd = 'C';
  188.         Kermit.ids_title = IDS_KRM_REMOTEHOST;
  189.         Kermit.nullstrOK = FALSE;
  190.         Kermit.sstate = 'c';
  191.         boxstr = MAKEINTRESOURCE(DT_KRM_GETFILE);
  192.         fp = MakeProcInstance((FARPROC)GetFileList, hInstance);
  193.         if (DialogBox(hInstance, boxstr, hWnd, fp))
  194.         krmState = menuitem;
  195.         FreeProcInstance(fp);
  196.         break;
  197.  
  198.     case IDM_KRM_SEND:
  199.         Kermit.sstate = 's';
  200.         boxstr = MAKEINTRESOURCE(DT_KRM_SENDFILE);
  201.         fp = MakeProcInstance((FARPROC)SendFileDlgProc, hInstance);
  202.         if (DialogBox(hInstance, boxstr, hWnd, fp))
  203.         krmState = menuitem;
  204.         FreeProcInstance(fp);
  205.         break;
  206.  
  207.     case IDM_KRM_CWD:
  208.         Kermit.sstate = 'g';
  209.         boxstr = MAKEINTRESOURCE(DT_KRM_REMOTE2);
  210.         fp = MakeProcInstance((FARPROC)krmRemoteChdir, hInstance);
  211.         if (DialogBox(hInstance, boxstr, hWnd, fp))
  212.         krmState = menuitem;
  213.         FreeProcInstance(fp);
  214.         break;
  215.  
  216.     case IDM_KRM_REMOTEDIR:
  217.         Kermit.remotecmd = 'D';
  218.         Kermit.ids_title = IDS_KRM_REMOTEDIR;
  219.         Kermit.nullstrOK = TRUE;
  220.         Kermit.sstate = 'g';
  221.           boxstr = MAKEINTRESOURCE(DT_KRM_GETFILE);
  222.         fp = MakeProcInstance((FARPROC)krmRemoteCmdDlgBox, hInstance);
  223.         if (DialogBox(hInstance, boxstr, hWnd, fp))
  224.         krmState = menuitem;
  225.         FreeProcInstance(fp);
  226.         break;
  227.  
  228.     case IDM_KRM_REMOTETYPE:
  229.         Kermit.remotecmd = 'T';
  230.         Kermit.ids_title = IDS_KRM_REMOTETYPE;
  231.         Kermit.nullstrOK = FALSE;
  232.         Kermit.sstate = 'g';
  233.           boxstr = MAKEINTRESOURCE(DT_KRM_GETFILE);
  234.         fp = MakeProcInstance((FARPROC)krmRemoteCmdDlgBox, hInstance);
  235.         if (DialogBox(hInstance, boxstr, hWnd, fp))
  236.         krmState = menuitem;
  237.         FreeProcInstance(fp);
  238.         break;
  239.  
  240.     case IDM_KRM_REMOTEHELP:
  241.         Kermit.remotecmd = 'H';
  242.         Kermit.ids_title = IDS_KRM_REMOTEHELP;
  243.         Kermit.nullstrOK = TRUE;
  244.         Kermit.sstate = 'g';
  245.           boxstr = MAKEINTRESOURCE(DT_KRM_GETFILE);
  246.         fp = MakeProcInstance((FARPROC)krmRemoteCmdDlgBox, hInstance);
  247.         if (DialogBox(hInstance, boxstr, hWnd, fp))
  248.         krmState = menuitem;
  249.         FreeProcInstance(fp);
  250.         break;
  251.  
  252.     case IDM_KRM_REMOTEDEL:
  253.         Kermit.remotecmd = 'E';
  254.         Kermit.ids_title = IDS_KRM_REMOTEDEL;
  255.         Kermit.nullstrOK = FALSE;
  256.         Kermit.sstate = 'g';
  257.           boxstr = MAKEINTRESOURCE(DT_KRM_GETFILE);
  258.         fp = MakeProcInstance((FARPROC)krmRemoteCmdDlgBox, hInstance);
  259.         if (DialogBox(hInstance, boxstr, hWnd, fp))
  260.         krmState = menuitem;
  261.         FreeProcInstance(fp);
  262.         break;
  263.  
  264.     case IDM_KRM_REMOTEWHO:
  265.         Kermit.remotecmd = 'W';
  266.         Kermit.ids_title = IDS_KRM_REMOTEWHO;
  267.         Kermit.nullstrOK = TRUE;
  268.         Kermit.sstate = 'g';
  269.           boxstr = MAKEINTRESOURCE(DT_KRM_GETFILE);
  270.         fp = MakeProcInstance((FARPROC)krmRemoteCmdDlgBox, hInstance);
  271.         if (DialogBox(hInstance, boxstr, hWnd, fp))
  272.         krmState = menuitem;
  273.         FreeProcInstance(fp);
  274.         break;
  275.  
  276.     case IDM_KRM_REMOTESPACE:
  277.         Kermit.remotecmd = 'U';
  278.         Kermit.ids_title = IDS_KRM_REMOTESPACE;
  279.         Kermit.nullstrOK = TRUE;
  280.         Kermit.sstate = 'g';
  281.           boxstr = MAKEINTRESOURCE(DT_KRM_GETFILE);
  282.         fp = MakeProcInstance((FARPROC)krmRemoteCmdDlgBox, hInstance);
  283.         if (DialogBox(hInstance, boxstr, hWnd, fp))
  284.         krmState = menuitem;
  285.         FreeProcInstance(fp);
  286.         break;
  287.     }
  288. }
  289.  
  290. /* init protocol */
  291. void tinit(HWND hWnd, int mode)
  292. {
  293.  
  294.     HANDLE hInstance = (HANDLE)GetWindowWord(hWnd, GWW_HINSTANCE);
  295.     FARPROC fp;
  296.     TEXTMETRIC TM;
  297.     HDC hDC;
  298.  
  299.     Kermit.fpTimer = MakeProcInstance((FARPROC)krmDoTimeout, hInstance);
  300.  
  301.     hDC = GetDC(hWnd);
  302.     GetTextMetrics(hDC, &TM);
  303.     Kermit.DispCharWidth = TM.tmAveCharWidth;
  304.     Kermit.DispCharHeight = TM.tmHeight + TM.tmExternalLeading;
  305.     ReleaseDC(hWnd, hDC);
  306.  
  307.     krmGrayMenus(hWnd, mode, MF_GRAYED);
  308.  
  309.     fp = MakeProcInstance((FARPROC)krmShowChildren, hInstance);
  310.     EnumChildWindows(hWnd, fp, (LONG)SW_HIDE);
  311.     FreeProcInstance(fp);
  312.  
  313.     switch(mode) {
  314.     case IDM_KRM_SEND:
  315.         if (Kermit.waitsendtime > 0) {
  316.         Kermit.waitsend = TRUE;
  317.             SetTimer(hWnd,KRM_WAITSEND,Kermit.waitsendtime,Kermit.fpTimer);
  318.         }
  319.     case IDM_KRM_RECEIVE:
  320.     case IDM_KRM_GET:
  321.         fpXfer = MakeProcInstance(krmXferDlgBox, hInstance);
  322.         hWndXfer = CreateDialog(hInstance,MAKEINTRESOURCE(DT_KRM_XFER),
  323.                         hWnd,fpXfer);
  324.         break;
  325.     }
  326.  
  327.     Kermit.numtry = 0;
  328.     Kermit.pktnum = 0;
  329.     Kermit.pktcount = 0;
  330.  
  331.     Kermit.retrycount = 0;
  332.     Kermit.bytesmoved = 0;
  333.     Kermit.filesize = 0;
  334.     Kermit.percentage = 0;
  335.  
  336.     Kermit.displayfile = 0;
  337.  
  338.     Kermit.inpacket = FALSE;
  339.     Kermit.fileabort = FALSE;
  340.     Kermit.batchabort = FALSE;
  341.     Kermit.protocolabort = FALSE;
  342.     Kermit.newname_flag = FALSE;
  343.  
  344.     Kermit.chksumtype = 1;
  345.     remote.chksumtype = local.chksumtype;
  346.  
  347.     Kermit.ebqflg = FALSE;
  348.     Kermit.ebq = 0;
  349.     Kermit.rqf = -1;
  350.     local.binquote = 'Y';
  351.  
  352.     Kermit.rptflg = FALSE;
  353.  
  354.     Kermit.hInFile = Kermit.hOutFile = NULL;
  355.     Kermit.filename = NULL;
  356.  
  357.     Kermit.mstimeout = 1000 * remote.timeout;
  358.     Kermit.timeout = FALSE;
  359.  
  360.     rcvpkt.state = PS_SYNCH;
  361.     rcvpkt.type = 'N';
  362.     rcvpkt.num = 0;
  363.  
  364.     sndpkt.len = 0;
  365. }
  366.  
  367. /* hide or show terminal and status windows */
  368. BOOL FAR PASCAL krmShowChildren(HWND hWnd, LONG lParam)
  369. {
  370.     ShowWindow(hWnd, LOWORD(lParam));
  371.     return TRUE;
  372. }
  373.  
  374. /* gray or restore menus */
  375. static void NEAR krmGrayMenus(HWND hWnd, int mode, int style)
  376. {
  377.  
  378.     register int i;
  379.     register HMENU hMenu = GetMenu(hWnd);
  380.     int opstyle, checkstyle;
  381.  
  382.     opstyle = (style == MF_GRAYED) ? MF_ENABLED : MF_GRAYED;
  383.     checkstyle = (style == MF_GRAYED) ? MF_CHECKED : MF_UNCHECKED;
  384.     
  385.     for (i = IDM_KRM_SEND; i <= IDM_KRM_REMOTEHOST; i++)
  386.     EnableMenuItem(hMenu, i, style);
  387.     for (i = IDM_CANCELFILE; i <= IDM_CANCELPROTOCOL; i++)
  388.     EnableMenuItem(hMenu, i, opstyle);
  389.     CheckMenuItem(hMenu, mode, checkstyle);
  390. }
  391.  
  392. /* show result of transfer based on exit state */
  393. static void NEAR krmShowResult(HWND hWnd, int mode)
  394. {
  395.  
  396.     int len;
  397.     int style;
  398.     int msgnum;
  399.     char szMessage[80];
  400.     char szCaption[40];
  401.     HANDLE hInstance = (HANDLE)GetWindowWord(hWnd, GWW_HINSTANCE);
  402.  
  403.     if ((msgnum = Kermit.sstate) >= 0)
  404.     msgnum = KRM_USERCNX;
  405.  
  406.     if (msgnum == KRM_COMPLETE)
  407.     style = MB_OK | MB_ICONASTERISK;
  408.    else
  409.         style = MB_OK | MB_ICONEXCLAMATION;
  410.  
  411.   /* get the string corresponding to msgnum */
  412.     LoadString(hInstance, IDS_KRM_KERMIT, (LPSTR)szCaption, sizeof(szCaption));
  413.     len = strlen(szCaption);
  414.     LoadString(hInstance, mode, (LPSTR)(szCaption+len),sizeof(szCaption) - len);
  415.     if (((msgnum == KRM_COMPLETE) && (rcvpkt.len > 0)) ||
  416.         ((msgnum == KRM_ERROR_PKT) && (rcvpkt.len > 0)))  
  417.     strcpy(szMessage,rcvpkt.data);
  418.     else
  419.         LoadString(hInstance, msgnum, (LPSTR)szMessage, sizeof(szMessage));
  420.  
  421.   /* put up this simple message box */
  422.     if (Kermit.bell)
  423.     MessageBeep(style);
  424.  
  425.     MessageBox(hWnd,(LPSTR)szMessage, (LPSTR)szCaption, style);
  426. }
  427.  
  428. /* reset things after transaction */
  429. static void near ResetFTParams(HWND hWnd, int mode)
  430. {
  431.  
  432.     FARPROC fp;
  433.     HANDLE hInstance = (HANDLE)GetWindowWord(hWnd, GWW_HINSTANCE);
  434.  
  435.     KillTimer(hWnd, KRM_WAITPACKET);
  436.     krmGrayMenus(hWnd, mode, MF_ENABLED);
  437.     krmShowResult(hWnd, mode);
  438.  
  439.     switch(mode) {
  440.     case IDM_KRM_RECEIVE:
  441.     case IDM_KRM_GET:
  442.     case IDM_KRM_SEND:
  443.         if (hWndXfer != NULL) {
  444.         DestroyWindow(hWndXfer);
  445.         hWndXfer = NULL;
  446.         FreeProcInstance(fpXfer);
  447.         }
  448.         break;
  449.  
  450.     case IDM_KRM_BYE:
  451.         if (Kermit.sstate == KRM_COMPLETE)
  452.             PostMessage(hWnd, WM_SYSCOMMAND, SC_CLOSE,0L);
  453.         break;
  454.     }
  455.  
  456.     if (DWnd.hVidBuffer != NULL) {
  457.     DWnd.pVidBuffer = NULL;
  458.     LocalUnlock(DWnd.hVidBuffer);
  459.     DWnd.hVidBuffer = LocalFree(DWnd.hVidBuffer);
  460.     InvalidateRect(hWnd, (LPRECT)NULL, TRUE);
  461.     }
  462.  
  463.     fp = MakeProcInstance((FARPROC)krmShowChildren, hInstance);
  464.     EnumChildWindows(hWnd, fp, (LONG)SW_RESTORE);
  465.     FreeProcInstance(fp);
  466.  
  467.     if (Kermit.hRemoteCommand != NULL) {
  468.     Kermit.pRemoteCommand = NULL;
  469.     LocalUnlock(Kermit.hRemoteCommand);
  470.     Kermit.hRemoteCommand = LocalFree(Kermit.hRemoteCommand);
  471.     }
  472.  
  473.     if (Kermit.hfilelist != NULL) {
  474.     Kermit.pfilelist = NULL;
  475.     LocalUnlock(Kermit.hfilelist);
  476.     Kermit.hfilelist = LocalFree(Kermit.hfilelist);
  477.     }
  478.     FreeProcInstance(Kermit.fpTimer);
  479. }
  480.  
  481. /* adjust height of long displays if window is resized */
  482. void krmAdjustHeight(short width, short height)
  483. {
  484.      
  485.     DWnd.Width = width;
  486.     DWnd.Height = height;
  487.     DWnd.Ypos = height - DWnd.CharHeight - 1;
  488.     InvalidateRect(DWnd.hWnd, (LPRECT)NULL, TRUE);
  489. }
  490.  
  491. /* init display for long replies */
  492. BOOL krmInitMainDisplay(HWND hWnd, short cwidth, short cheight)
  493. {
  494.  
  495.     HDC hDC;
  496.     RECT drect;
  497.  
  498.     DWnd.hWnd = hWnd;
  499.     DWnd.CharWidth = cwidth;
  500.     DWnd.CharHeight = cheight;
  501.  
  502.     if (DWnd.MaxCols == 0) {
  503.     hDC = GetDC(hWnd);
  504.     DWnd.MaxCols = GetDeviceCaps(hDC, HORZRES) / cwidth; 
  505.     DWnd.MaxLines = GetDeviceCaps(hDC, VERTRES) / cheight;
  506.         DWnd.MaxLineLength = DWnd.MaxCols + 1;
  507.     ReleaseDC(hWnd, hDC);
  508.     }
  509.     GetClientRect(hWnd, (LPRECT)&drect);
  510.     DWnd.Width = drect.right;
  511.     DWnd.Height = drect.bottom;
  512.  
  513.     if (DWnd.hVidBuffer = LocalAlloc(LPTR,DWnd.MaxLines * DWnd.MaxLineLength)) {
  514.     DWnd.pVidBuffer = LocalLock(DWnd.hVidBuffer);
  515.     DWnd.oCurrentLine = 0;
  516.     DWnd.oVidLastLine = DWnd.MaxLineLength * (DWnd.MaxLines - 1);
  517.     DWnd.CurrLineOffset = 0;
  518.     DWnd.Xpos = 0;
  519.         DWnd.Ypos = DWnd.Height - DWnd.CharHeight - 1;
  520.     return TRUE;
  521.     }
  522.     return (FALSE);
  523. }
  524.  
  525. /* display received strings on long replies */
  526. void krmMainStringDisplay(HWND hWnd, BYTE *str, short len)
  527. {
  528.  
  529.     HDC hDC;
  530.     register BYTE *ptr;
  531.     register short ctr;
  532.     short cols = DWnd.MaxCols;
  533.     short width = DWnd.Width;
  534.     short toff, txpos;
  535.     BYTE *tBuf;
  536.  
  537.     while (len) {
  538.     ptr = str;
  539.     ctr = 0;
  540.     txpos = DWnd.Xpos;
  541.         tBuf = DWnd.pVidBuffer + DWnd.oCurrentLine;
  542.     toff =  DWnd.CurrLineOffset;
  543.   /* first loop on any printable characters until none left or end of line */
  544.  
  545.     while ((*ptr &= 0x7f) >= SP) {
  546.         if ((len) && (toff < cols))    {
  547.         ctr += 1;
  548.         *(tBuf + toff++) = *ptr++;    /* store them in the buffer */
  549.         txpos += DWnd.CharWidth;
  550.         len -= 1;
  551.         }
  552.         else        /* quit if we find a control character */
  553.         break;
  554.     }
  555.     if (ctr) {        /* if we have some characters, show them */
  556.         if (!IsIconic(hWnd)) {
  557.             hDC = GetDC(hWnd);
  558.         SetBkMode(hDC, TRANSPARENT);
  559.         SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
  560.             TextOut(hDC, DWnd.Xpos, DWnd.Ypos, (LPSTR)str, ctr);
  561.             ReleaseDC(hWnd, hDC);
  562.         }
  563.     /* if not at end of line yet */
  564.         if (toff < cols) {        /* update buffer and caret variables */ 
  565.         DWnd.CurrLineOffset = toff;
  566.         DWnd.Xpos = txpos;
  567.         }
  568.         else {        /* end of line, so wrap */
  569.         DoMCR(&DWnd);
  570.         DoMLF(&DWnd);
  571.         }
  572.     }
  573.     while ((*ptr &= 0x7f) < SP) {    /* now loop on any control characters */
  574.         if (len) {
  575.         switch (*ptr) {
  576.             case BEL:
  577.             MessageBeep(0);
  578.             break;
  579.             case HT:
  580.             DoMTab(&DWnd);
  581.             break;
  582.             case BS:
  583.             DoMBS(&DWnd);    
  584.             break;
  585.             case LF:
  586.             DoMLF(&DWnd);
  587.             break;
  588.             case CR:
  589.             DoMCR(&DWnd);
  590.             break;
  591.         }
  592.         len -= 1;        /* reduce buffer count */
  593.         ptr++;            /* update pointer */
  594.         }
  595.         else
  596.         break;            /* no more control characters */
  597.     }
  598.     str = ptr;    /* reset string pointer and do again if len > 0 */
  599.     }
  600. }
  601.  
  602. /* do carriage return */
  603. static void NEAR DoMCR(PDISPLAYWND pDWnd)
  604. {
  605.  
  606.     pDWnd->Xpos = pDWnd->CurrLineOffset = 0;
  607.  
  608. }
  609.  
  610. /* Do a line feed */
  611. static void NEAR DoMLF(PDISPLAYWND pDWnd)
  612. {
  613.  
  614.     register BYTE *pCurr;
  615.     register int i;
  616.     short cols = pDWnd->MaxCols;
  617.     short offset;
  618.     RECT scrollrect;
  619.  
  620.  
  621.   /* update the circular text buffer parameters */
  622.  
  623.     if ((pDWnd->oCurrentLine += pDWnd->MaxLineLength) > pDWnd->oVidLastLine)
  624.     pDWnd->oCurrentLine = 0;
  625.     pCurr = pDWnd->pVidBuffer + pDWnd->oCurrentLine;
  626.     offset = pDWnd->CurrLineOffset;
  627.  
  628.   /* fill in any places from beginning of line with spaces */
  629.  
  630.     for (i = 0; i < offset; i++)
  631.     *(pCurr + i) = SP;
  632.  
  633.   /* fill in the rest with nuls */
  634.  
  635.     for (i = offset; i < cols; i++)
  636.         *(pCurr + i) = NUL;
  637.  
  638.   /* now move the tty window up exactly one line and refresh it */
  639.     if (!IsIconic(pDWnd->hWnd)) {
  640.         GetClientRect(pDWnd->hWnd, (LPRECT)&scrollrect);
  641.         ScrollWindow(pDWnd->hWnd,0,-pDWnd->CharHeight,
  642.              (LPRECT)&scrollrect,(LPRECT)NULL);
  643.         UpdateWindow(pDWnd->hWnd);
  644.     }
  645. }
  646.  
  647. /* Horizontal tab */
  648. static void NEAR DoMTab(PDISPLAYWND pDWnd)
  649. {
  650.  
  651.     RECT myrect;
  652.     BYTE *pCurr = pDWnd->pVidBuffer + pDWnd->oCurrentLine;
  653.     short cols = pDWnd->MaxCols;
  654.     register short xpos = pDWnd->Xpos;        
  655.     register short curoffset = pDWnd->CurrLineOffset;
  656.  
  657.     if (curoffset < (cols - 1)) {
  658.         do {
  659.         if (*(pCurr + curoffset) == NUL)  /* if null, replace with space */
  660.             *(pCurr + curoffset) = SP;
  661.         curoffset += 1;        /* update offsets */
  662.         xpos += DWnd.CharWidth;
  663.         } while ((curoffset % 8 != 0) && (curoffset < (cols - 1)));
  664.  
  665.     /* now invalidate the part of the screen affected */
  666.        if (!IsIconic(pDWnd->hWnd)) {
  667.         SetRect((LPRECT)&myrect, pDWnd->Xpos, pDWnd->Ypos, pDWnd->Width,
  668.                             pDWnd->Height);
  669.         InvalidateRect(pDWnd->hWnd, (LPRECT)&myrect, TRUE);
  670.     }
  671.     /* finally, reset the tty window variables */
  672.         pDWnd->Xpos = xpos;
  673.         pDWnd->CurrLineOffset = curoffset;
  674.     }
  675. }
  676.  
  677. /* Backspace */
  678. static void NEAR DoMBS(PDISPLAYWND pDWnd)
  679. {
  680.  
  681.   /* don't back up if at beginning of line! */
  682.     if (pDWnd->CurrLineOffset > 0) {
  683.     pDWnd->Xpos -= pDWnd->CharWidth;
  684.     pDWnd->CurrLineOffset -= 1;
  685.     }
  686. }
  687.