home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / ftes46b5.zip / ftes46b5 / src / con_os2.cpp < prev    next >
Text File  |  1998-02-01  |  33KB  |  1,220 lines

  1. /*    con_os2.cpp
  2.  *
  3.  *    Copyright (c) 1994-1998, Marko Macek
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  */
  9.  
  10. // include
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <assert.h>
  16. #include <signal.h>
  17.  
  18. #include "sysdep.h"
  19. #include "console.h"
  20. #include "gui.h"
  21.  
  22. extern int ShowVScroll;
  23.  
  24. //#define INCL_NOPM
  25. //#define INCL_WINSWITCHLIST
  26. #define INCL_WIN
  27. #define INCL_SUB
  28. #define INCL_KBD
  29. #define INCL_VIO
  30. #define INCL_MOU
  31. #define INCL_BASE
  32. #define INCL_DOS
  33. #define INCL_DOSDEVIOCTL
  34.  
  35. #include <stdlib.h>
  36. #include <process.h>
  37.  
  38. #ifndef OS2_INCLUDED
  39. #include <os2.h>
  40. #endif
  41.  
  42. #define MAX_PIPES 4
  43. #define PIPE_BUFLEN 4096
  44.  
  45. typedef struct {
  46.     int used;
  47.     int id;
  48.     int reading, stopped;
  49.     TID tid;
  50.     HMTX Access;
  51.     HEV ResumeRead;
  52.     HEV NewData;
  53.     char *buffer;
  54.     int buflen;
  55.     int bufused;
  56.     int bufpos;
  57.     EModel *notify;
  58.     char *Command;
  59.     int RetCode;
  60.     int DoTerm;
  61. } GPipe;
  62.  
  63. static GPipe Pipes[MAX_PIPES] = {
  64.     { 0 }, { 0 }, { 0 }, { 0 }
  65. };
  66.  
  67. static long MouseAutoDelay = 400;
  68. static long MouseAutoRepeat = 5;
  69. static long MouseMultiClick = 300;
  70.  
  71. static Initialized = 0;
  72. static MousePresent = 0;
  73. static int CursorVisible = 1; /* 1 means visible */
  74. static int MouseVisible = 0; /* 0 means hidden */
  75. static TEvent MouseEv = { evNone };
  76. static TEvent EventBuf = { evNone };
  77. static HMOU MouseHandle = 0;
  78. static KBDINFO SaveKbdState;
  79.  
  80. // misc
  81.  
  82. static void DrawCursor(int Show) {
  83.     VIOCURSORINFO vci;
  84.     VioGetCurType(&vci, 0);
  85.     if (Show == 1)
  86.         vci.attr = 1;
  87.     else
  88.         vci.attr = -1;
  89.     VioSetCurType(&vci, 0);
  90. }
  91.  
  92. static void DrawMouse(int Show) {
  93.     if (!MousePresent) return;
  94.     if (Show == 1) {
  95.         MouDrawPtr(MouseHandle);
  96.     } else {
  97.         NOPTRRECT npr;
  98.         int W, H;
  99.  
  100.         npr.row = 0;
  101.         npr.col = 0;
  102.         ConQuerySize(&W, &H);
  103.         npr.cCol = (USHORT) (W - 1);
  104.         npr.cRow = (USHORT) (H - 1);
  105.         MouRemovePtr(&npr, MouseHandle);
  106.     }
  107. }
  108.  
  109. static struct { // TransCharScan
  110.     USHORT CharScan;
  111.     TKeyCode KeyCode;
  112. } TransCharScan[] = {
  113.     { 0x0100, kbEsc },                     { 0x011B, kbEsc },
  114.     { 0x1C0D, kbEnter },                   { 0x1C0A, kbEnter },
  115.     { 0x1C00, kbEnter },                   { 0xE00D, kbEnter | kfGray },
  116.     { 0xA600, kbEnter | kfGray },          { 0xE00A, kbEnter | kfGray },
  117.     { 0x0E08, kbBackSp },                  { 0x0E7F, kbBackSp },
  118.     { 0x0E00, kbBackSp },                  { 0x0F09, kbTab },
  119.     { 0x9400, kbTab },                     { 0xA500, kbTab },
  120.     { 0x0F00, kbTab },                     { 0x4E00, '+' | kfGray },
  121.     { 0x9000, '+' | kfGray },              { 0x4E2B, '+' | kfGray },
  122.     { 0x4A00, '-' | kfGray },              { 0x8E00, '-' | kfGray },
  123.     { 0x4A2D, '-' | kfGray },              { 0x3700, '*' | kfGray },
  124.     { 0x9600, '*' | kfGray },              { 0x372A, '*' | kfGray },
  125.     { 0xE02F, '/' | kfGray },              { 0xA400, '/' | kfGray },
  126.     { 0x9500, '/' | kfGray },              { 0x0300, 0 }
  127. };
  128.  
  129. static struct { // TransScan
  130.     int ScanCode;
  131.     TKeyCode KeyCode;
  132. } TransScan[] = {
  133.     { 0x78, '1' }, { 0x79, '2' }, { 0x7A, '3' }, { 0x7B, '4' }, { 0x7C, '5' },
  134.     { 0x7D, '6' }, { 0x7E, '7' }, { 0x7F, '8' }, { 0x80, '9' }, { 0x81, '0' },
  135.  
  136.     { 0x10, 'Q' }, { 0x11, 'W' }, { 0x12, 'E' }, { 0x13, 'R' }, { 0x14, 'T' },
  137.     { 0x15, 'Y' }, { 0x16, 'U' }, { 0x17, 'I' }, { 0x18, 'O' }, { 0x19, 'P' },
  138.  
  139.     { 0x1E, 'A' }, { 0x1F, 'S' }, { 0x20, 'D' }, { 0x21, 'F' }, { 0x22, 'G' },
  140.     { 0x23, 'H' }, { 0x24, 'J' }, { 0x25, 'K' }, { 0x26, 'L' },
  141.  
  142.     { 0x2C, 'Z' }, { 0x2D, 'X' }, { 0x2E, 'C' }, { 0x2F, 'V' }, { 0x30, 'B' },
  143.     { 0x31, 'N' }, { 0x32, 'M' },
  144.  
  145.     { 0x29, '`' }, { 0x82, '-' }, { 0x83, '=' }, { 0x2B, '\\' }, { 0x1A, '[' },
  146.     { 0x1B, ']' }, { 0x27, ';' }, { 0x28, '\'' }, { 0x33, ',' }, { 0x34, '.' },
  147.     { 0x35, '/' }, { 0x37, '*' }, { 0x4E, '+' }, { 0x4A, '-' },
  148.  
  149.     { 0x3B, kbF1    },  { 0x3C, kbF2    },  { 0x3D, kbF3    },
  150.     { 0x3E, kbF4    },  { 0x3F, kbF5    },  { 0x40, kbF6    },
  151.     { 0x41, kbF7    },  { 0x42, kbF8    },  { 0x43, kbF9    },
  152.     { 0x44, kbF10   },  { 0x85, kbF11   },  { 0x86, kbF12   },
  153.  
  154.     { 0x54, kbF1    },  { 0x55, kbF2    },  { 0x56, kbF3    },
  155.     { 0x57, kbF4    },  { 0x58, kbF5    },  { 0x59, kbF6    },
  156.     { 0x5A, kbF7    },  { 0x5B, kbF8    },  { 0x5C, kbF9    },
  157.     { 0x5D, kbF10   },  { 0x87, kbF11   },  { 0x88, kbF12   },
  158.  
  159.     { 0x5E, kbF1    },  { 0x5F, kbF2    },  { 0x60, kbF3    },
  160.     { 0x61, kbF4    },  { 0x62, kbF5    },  { 0x63, kbF6    },
  161.     { 0x64, kbF7    },  { 0x65, kbF8    },  { 0x66, kbF9    },
  162.     { 0x67, kbF10   },  { 0x89, kbF11   },  { 0x8A, kbF12   },
  163.  
  164.     { 0x68, kbF1    },  { 0x69, kbF2    },  { 0x6A, kbF3    },
  165.     { 0x6B, kbF4    },  { 0x6C, kbF5    },  { 0x6D, kbF6    },
  166.     { 0x6E, kbF7    },  { 0x6F, kbF8    },  { 0x70, kbF9    },
  167.     { 0x71, kbF10   },  { 0x8B, kbF11   },  { 0x8C, kbF12   },
  168.  
  169.     { 0x47, kbHome  },  { 0x48, kbUp    },  { 0x49, kbPgUp  },
  170.     { 0x4B, kbLeft  },  { 0x4C, kbCenter},  { 0x4D, kbRight },
  171.     { 0x4F, kbEnd   },  { 0x50, kbDown  },  { 0x51, kbPgDn  },
  172.     { 0x52, kbIns   },  { 0x53, kbDel   },
  173.  
  174.     { 0x77, kbHome  },  { 0x8D, kbUp    },  { 0x84, kbPgUp  },
  175.     { 0x73, kbLeft  },                      { 0x74, kbRight },
  176.     { 0x75, kbEnd   },  { 0x91, kbDown  },  { 0x76, kbPgDn  },
  177.     { 0x92, kbIns   },  { 0x93, kbDel   },
  178.  
  179.     { 0x97, kbHome  | kfGray },  { 0x98, kbUp    | kfGray },  { 0x99, kbPgUp  | kfGray },
  180.     { 0x9B, kbLeft  | kfGray },                               { 0x9D, kbRight | kfGray },
  181.     { 0x9F, kbEnd   | kfGray },  { 0xA0, kbDown  | kfGray },  { 0xA1, kbPgDn  | kfGray },
  182.     { 0xA2, kbIns   | kfGray },  { 0xA3, kbDel   | kfGray }
  183. };
  184.  
  185. int ReadKbdEvent(TEvent *Event, int Wait) {
  186.     KBDKEYINFO ki;
  187.     UCHAR CharCode, ScanCode;
  188.     ULONG KeyCode, KeyFlags;
  189.     USHORT CharScan, Flags;
  190.     static USHORT PrevFlags = 0;
  191.     unsigned int I;
  192.  
  193.     Event->What = evNone;
  194.     KbdCharIn(&ki, IO_NOWAIT, 0);
  195.     if (!(ki.fbStatus & 0x40)) return 0;
  196.  
  197.     Event->What = evKeyDown;
  198.  
  199.     CharCode = ki.chChar;
  200.     ScanCode = ki.chScan;
  201.     CharScan = (USHORT)((((USHORT)ScanCode) << 8) | ((USHORT)CharCode));
  202.     Flags = ki.fsState;
  203.     KeyCode = 0;
  204.     KeyFlags = 0;
  205.  
  206. /*   printf("Key: %X %X %X %X %X \n", (unsigned long) ki.bNlsShift, (unsigned long) ki.fbStatus, (unsigned long) Flags, (unsigned long) CharCode, (unsigned long) ScanCode);*/
  207.  
  208.     if ((Flags & (LEFTSHIFT | RIGHTSHIFT)) != 0) KeyFlags |= kfShift;
  209.     if ((Flags & (LEFTCONTROL | RIGHTCONTROL)) != 0) KeyFlags |= kfCtrl;
  210.  
  211. /*    cpCount = sizeof(cpList);*/
  212. /*    rc = DosQueryCp(sizeof(cpList), cpList, &cpCount);  // get active code page*/
  213.     if (CharCode != 0) {
  214.         if ((Flags & (LEFTALT)) != 0) KeyFlags |= kfAlt;
  215.     } else {
  216.         if ((Flags & (LEFTALT | RIGHTALT)) != 0) KeyFlags |= kfAlt;
  217.     }
  218. /*    if (rc != 0) printf("rc = %d\n", rc);*/
  219.  
  220.     if (CharScan == 0) { /* shift/alt/ctrl/caps/scroll/num */
  221.  
  222.     } else if (ScanCode == 0) { /* alt numeric */
  223.         KeyCode = CharCode;
  224.         KeyFlags |= kfAltXXX;
  225.     } else { /* now check special combinations */
  226.         for (I = 0; I < sizeof(TransCharScan)/sizeof(TransCharScan[0]); I++)
  227.             if (TransCharScan[I].CharScan == CharScan) {
  228.                 KeyCode = TransCharScan[I].KeyCode;
  229.                 break;
  230.             }
  231.         if (KeyCode == 0) {
  232.             if ((CharCode == 0) || (CharCode == 0xE0)) {
  233.                 if (CharCode == 0xE0)
  234.                     KeyFlags |= kfGray;
  235.                 for (I = 0; I < sizeof(TransScan)/sizeof(TransScan[0]); I++)
  236.                     if (TransScan[I].ScanCode == ScanCode) {
  237.                         KeyCode = TransScan[I].KeyCode;
  238.                         break;
  239.                     }
  240.             } else {
  241.                 if (CharCode < 32)
  242.                     if (KeyFlags & kfCtrl)
  243.                         CharCode += 64;
  244.                 KeyCode = CharCode;
  245.             }
  246.         }
  247.     }
  248.     Event->Key.Code = KeyCode | KeyFlags;
  249.     PrevFlags = Flags;
  250.     return 1;
  251. }
  252.  
  253. #define TM_DIFF(x,y) ((long)(((long)(x) < (long)(y)) ? ((long)(y) - (long)(x)) : ((long)(x) - (long)(y))))
  254.  
  255. int ReadMouseEvent(TEvent *Event, ULONG EventMask) {
  256.     static unsigned short PrevState = 0;
  257.     static unsigned short PrevButtons = 0;
  258.     static TEvent LastMouseEvent = { evNone };
  259.     static ULONG LastEventTime = 0;
  260.     static ULONG LastClick = 0;
  261.     static ULONG LastClickTime = 0;
  262.     static ULONG LastClickCount = 0;
  263.     MOUEVENTINFO mi;
  264.     unsigned short Buttons, State, Btn;
  265.     USHORT fWait = MOU_NOWAIT;
  266.     MOUQUEINFO mq;
  267.     ULONG CurTime;
  268.  
  269.     DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &CurTime, 4);
  270.  
  271.     Event->What = evNone;
  272.     MouGetNumQueEl(&mq, MouseHandle);
  273.     if (mq.cEvents == 0) {
  274.         if (LastMouseEvent.What == evMouseAuto && (EventMask & evMouseAuto)) {
  275.             if (TM_DIFF(CurTime, LastEventTime) >= MouseAutoRepeat) {
  276.                 *Event = LastMouseEvent;
  277.                 DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &LastEventTime, 4);
  278.                 return 1;
  279.             }
  280.         }
  281.         if ((LastMouseEvent.What == evMouseDown || LastMouseEvent.What == evMouseMove)
  282.             &&
  283.             (LastMouseEvent.Mouse.Buttons)
  284.             && (EventMask & evMouseAuto))
  285.         {
  286.             if (TM_DIFF(CurTime, LastEventTime) >= MouseAutoDelay) {
  287.                 LastMouseEvent.What = evMouseAuto;
  288.                 *Event = LastMouseEvent;
  289.                 DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &LastEventTime, 4);
  290.                 return 1;
  291.             }
  292.         }
  293.         return 0;
  294.     }
  295.  
  296.     if (MouReadEventQue(&mi, &fWait, MouseHandle) != 0) return 0;
  297.     Event->Mouse.X = mi.col;
  298.     Event->Mouse.Y = mi.row;
  299.     State = mi.fs;
  300.     Btn = Buttons = ((State & (2 | 4))?1:0) |
  301.                     ((State & (8 | 16))?2:0) |
  302.                     ((State & (32 | 64))?4:0);
  303.     if (Buttons != PrevButtons) {
  304.         Buttons ^= PrevButtons;
  305.         if (PrevButtons & Buttons)
  306.             Event->What = evMouseUp;
  307.         else
  308.             Event->What = evMouseDown;
  309.     } else {
  310.         Event->What = evMouseMove;
  311.         if (Event->Mouse.X == LastMouseEvent.Mouse.X &&
  312.             Event->Mouse.Y == LastMouseEvent.Mouse.Y)
  313.             return 0;
  314.     }
  315.     Event->Mouse.Buttons = Buttons;
  316.     Event->Mouse.Count = 1;
  317.     PrevState = State;
  318.     PrevButtons = Btn;
  319.  
  320.     if (Event->What == evMouseDown) {
  321.         if (LastClickCount) {
  322.             if (LastClick == Event->Mouse.Buttons) {
  323.                 if (TM_DIFF(CurTime, LastClickTime) <= MouseMultiClick) {
  324.                     Event->Mouse.Count = ++LastClickCount;
  325.                 } else {
  326.                     LastClickCount = 0;
  327.                 }
  328.             } else {
  329.                 LastClick = 0;
  330.                 LastClickCount = 0;
  331.                 LastClickTime = 0;
  332.             }
  333.         }
  334.  
  335.         LastClick = Event->Mouse.Buttons;
  336.         if (LastClickCount == 0)
  337.             LastClickCount = 1;
  338.         DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &LastClickTime, 4);
  339.     }
  340. /*    if (Event->What == evMouseMove) {
  341.         LastClick = 0;
  342.         LastClickCount = 0;
  343.         LastClickTime = 0;
  344.     }*/
  345.     {
  346.         KBDINFO ki;
  347.         USHORT Flags;
  348.         TKeyCode KeyFlags = 0;
  349.  
  350.         ki.cb = sizeof(ki);
  351.         KbdGetStatus(&ki, 0);
  352.         Flags = ki.fsState;
  353.  
  354.         if ((Flags & (LEFTSHIFT | RIGHTSHIFT)) != 0) KeyFlags |= kfShift;
  355.         if ((Flags & (LEFTCONTROL | RIGHTCONTROL)) != 0) KeyFlags |= kfCtrl;
  356.         if ((Flags & (LEFTALT | RIGHTALT)) != 0) KeyFlags |= kfAlt;
  357.  
  358.         Event->Mouse.KeyMask = KeyFlags;
  359.     }
  360.  
  361.     LastMouseEvent = *Event;
  362.     DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &LastEventTime, 4);
  363.     return 1;
  364. }
  365.  
  366.  
  367. int ConClear() {
  368.     int W, H;
  369.     TDrawBuffer B;
  370.  
  371.     MoveChar(B, 0, ConMaxCols, ' ', 0x07, 1);
  372.     if ((ConQuerySize(&W, &H) == 0) &&
  373.         ConSetBox(0, 0, W, H, B[0])) return 0;
  374.     return -1;
  375. }
  376.  
  377. int ConPutBox(int X, int Y, int W, int H, PCell Cell) {
  378.     int I;
  379.     int MX, MY;
  380.     int MouseHidden = 0;
  381.     unsigned char *p = (unsigned char *) Cell;
  382.     if (MouseVisible)
  383.         ConQueryMousePos(&MX, &MY);
  384.  
  385.     for (I = 0; I < H; I++) {
  386.         if (MouseVisible)
  387.             if (Y + I == MY)
  388.                 if ((MX >= X) && (MX <= X + W)) {
  389.                     DrawMouse(0);
  390.                     MouseHidden = 1;
  391.                 }
  392.         VioWrtCellStr((PCH)p, (USHORT)(W << 1), (USHORT)(Y + I), (USHORT)X, 0);
  393.  
  394.         if (MouseHidden) {
  395.             DrawMouse(1);
  396.             MouseHidden = 0;
  397.         }
  398.         p += W << 1;
  399.     }
  400.     return 0;
  401. }
  402.  
  403. int ConGetBox(int X, int Y, int W, int H, PCell Cell) {
  404.     int I;
  405.     int MX, MY;
  406.     int MouseHidden = 0;
  407.     USHORT WW = (USHORT)(W << 1);
  408.     unsigned char *p = (unsigned char *) Cell;
  409.  
  410.     if (MouseVisible)
  411.         ConQueryMousePos(&MX, &MY);
  412.  
  413.     for (I = 0; I < H; I++) {
  414.         if (MouseVisible)
  415.             if (Y + I == MY)
  416.                 if (MX >= X && MX < X + W) {
  417.                     DrawMouse(0);
  418.                     MouseHidden = 1;
  419.                 }
  420.         VioReadCellStr((PCH)p, &WW, (USHORT)(Y + I), (USHORT)X, 0);
  421.  
  422.         if (MouseHidden) {
  423.             DrawMouse(1);
  424.             MouseHidden = 0;
  425.         }
  426.         p += W << 1;
  427.     }
  428.     return 0;
  429. }
  430.  
  431. int ConPutLine(int X, int Y, int W, int H, PCell Cell) {
  432.     int I;
  433.     int MX, MY;
  434.     int MouseHidden = 0;
  435.     unsigned char *p = (unsigned char *) Cell;
  436.     if (MouseVisible)
  437.         ConQueryMousePos(&MX, &MY);
  438.  
  439.     for (I = 0; I < H; I++) {
  440.     if (MouseVisible)
  441.         if (Y + I == MY)
  442.             if (MX >= X && MX < X + W) {
  443.                 DrawMouse(0);
  444.                 MouseHidden = 1;
  445.             }
  446.         VioWrtCellStr((PCH)p, (USHORT)(W << 1), (USHORT)(Y + I), (USHORT)X, 0);
  447.  
  448.         if (MouseHidden) {
  449.             DrawMouse(1);
  450.             MouseHidden = 0;
  451.         }
  452.     }
  453.     return 0;
  454. }
  455.  
  456. int ConSetBox(int X, int Y, int W, int H, TCell Cell) {
  457.     int I;
  458.     int MX, MY;
  459.     int MouseHidden = 0;
  460.     unsigned char *p = (unsigned char *) &Cell;
  461.     if (MouseVisible)
  462.         ConQueryMousePos(&MX, &MY);
  463.  
  464.     for (I = 0; I < H; I++) {
  465.         if (MouseVisible)
  466.             if (Y + I == MY)
  467.                 if (MX >= X && MX < X + W) {
  468.                     DrawMouse(0);
  469.                     MouseHidden = 1;
  470.                 }
  471.         VioWrtNCell((PCH)p, (USHORT)(W), (USHORT)(Y + I), (USHORT)X, 0);
  472.  
  473.         if (MouseHidden) {
  474.             DrawMouse(1);
  475.             MouseHidden = 0;
  476.         }
  477.     }
  478.     return 0;
  479. }
  480.  
  481. int ConScroll(int Way, int X, int Y, int W, int H, TAttr Fill, int Count) {
  482.     int MX, MY;
  483.     int MouseHidden = 0;
  484.     TCell FillCell = (TCell)(Fill << 8);
  485.  
  486.     if (MousePresent && MouseVisible) {
  487.         ConQueryMousePos(&MX, &MY);
  488.         if (MX >= X && MX < X + W && MY >= Y && MY < Y + H) {
  489.             DrawMouse(0);
  490.             MouseHidden = 1;
  491.         }
  492.     }
  493.  
  494.     switch (Way) {
  495.     case csUp:
  496.         VioScrollUp((USHORT)Y, (USHORT)X, (USHORT)(Y + H - 1), (USHORT)(X + W - 1), (USHORT)Count, (PBYTE)&FillCell, 0);
  497.         break;
  498.     case csDown:
  499.         VioScrollDn((USHORT)Y, (USHORT)X, (USHORT)(Y + H - 1), (USHORT)(X + W - 1), (USHORT)Count, (PBYTE)&FillCell, 0);
  500.         break;
  501.     case csLeft:
  502.         VioScrollLf((USHORT)Y, (USHORT)X, (USHORT)(Y + H - 1), (USHORT)(X + W - 1), (USHORT)Count, (PBYTE)&FillCell, 0);
  503.         break;
  504.     case csRight:
  505.         VioScrollRt((USHORT)Y, (USHORT)X, (USHORT)(Y + H - 1), (USHORT)(X + W - 1), (USHORT)Count, (PBYTE)&FillCell, 0);
  506.         break;
  507.     }
  508.     if (MouseHidden)
  509.         DrawMouse(1);
  510.     return 0;
  511. }
  512.  
  513. int ConSetSize(int X, int Y) {
  514.     VIOMODEINFO vmi;
  515.     int rc;
  516.  
  517.     vmi.cb = sizeof(VIOMODEINFO);
  518.     VioGetMode(&vmi, 0);
  519.     vmi.col = (USHORT)X;
  520.     vmi.row = (USHORT)Y;
  521.     vmi.cb = 2 + 1 + 1 + 2 + 2;
  522.     rc = VioSetMode(&vmi, 0);
  523.     if (rc == 0) return 0;
  524.     return -1;
  525. }
  526.  
  527. int ConQuerySize(int *X, int *Y) {
  528.     VIOMODEINFO vmi;
  529.  
  530.     vmi.cb = sizeof(VIOMODEINFO);
  531.     VioGetMode(&vmi, 0);
  532.     if (X) *X = vmi.col;
  533.     if (Y) *Y = vmi.row;
  534.     return 0;
  535. }
  536.  
  537. int ConSetCursorPos(int X, int Y) {
  538.     VioSetCurPos((USHORT)Y, (USHORT)X, 0);
  539.     return 0;
  540. }
  541.  
  542. int ConQueryCursorPos(int *X, int *Y) {
  543.     USHORT AX, AY;
  544.  
  545.     VioGetCurPos(&AY, &AX, 0);
  546.     if (X) *X = AX;
  547.     if (Y) *Y = AY;
  548.     return 0;
  549. }
  550.  
  551. int ConShowCursor() {
  552.     CursorVisible = 1;
  553.     DrawCursor(1);
  554.     return 0;
  555. }
  556.  
  557. int ConHideCursor() {
  558.     CursorVisible = 0;
  559.     DrawCursor(0);
  560.     return 0;
  561. }
  562.  
  563. int ConSetCursorSize(int Start, int End) {
  564.     VIOCURSORINFO ci;
  565.  
  566.     VioGetCurType(&ci, 0);
  567.     ci.yStart = -Start;
  568.     ci.cEnd = -End;
  569.     ci.cx = 0;
  570.     VioSetCurType(&ci, 0);
  571.     return 0;
  572. }
  573.  
  574. int ConSetMousePos(int X, int Y) {
  575.     PTRLOC mp;
  576.  
  577.     if (!MousePresent) return -1;
  578.     mp.col = (USHORT)X;
  579.     mp.row = (USHORT)Y;
  580.     MouSetPtrPos(&mp, MouseHandle);
  581.     return 0;
  582. }
  583.  
  584. int ConQueryMousePos(int *X, int *Y) {
  585.     PTRLOC mp;
  586.  
  587.     if (!MousePresent) return -1;
  588.     MouGetPtrPos(&mp, MouseHandle);
  589.     if (X) *X = mp.col;
  590.     if (Y) *Y = mp.row;
  591.     return 0;
  592. }
  593.  
  594. int ConShowMouse() {
  595.     MouseVisible = 1;
  596.     if (!MousePresent) return -1;
  597.     DrawMouse(1);
  598.     return 0;
  599. }
  600.  
  601. int ConHideMouse() {
  602.     MouseVisible = 0;
  603.     if (!MousePresent) return -1;
  604.     DrawMouse(0);
  605.     return 0;
  606. }
  607.  
  608. int ConMouseVisible() {
  609.     return (MouseVisible == 1);
  610. }
  611.  
  612. int ConQueryMouseButtons(int *ButtonCount) {
  613.     USHORT Count;
  614.     if (MouGetNumButtons(&Count, MouseHandle) != 0) return -1;
  615.     if (ButtonCount) *ButtonCount = Count;
  616.     return 0;
  617. }
  618.  
  619.  
  620.  
  621. int ConInit(int XSize, int YSize) {
  622.     USHORT MevMask = 127;
  623.  
  624.     if (Initialized)
  625.         return 0;
  626.  
  627.     EventBuf.What = evNone;
  628.     MousePresent = (MouOpen(NULL, &MouseHandle) == 0) ?1:0;
  629.  
  630.     if (MousePresent)
  631.         MouSetEventMask(&MevMask, MouseHandle);
  632.  
  633.     memset(&SaveKbdState, 0, sizeof(SaveKbdState));
  634.     SaveKbdState.cb = sizeof(SaveKbdState);
  635.     assert(KbdGetStatus(&SaveKbdState, 0) == 0);
  636.     ConContinue();
  637.  
  638.     Initialized = 1;
  639.  
  640.     return 0;
  641. }
  642.  
  643. int ConDone() {
  644.     return ConSuspend();
  645. }
  646.  
  647. int ConSuspend() {
  648.     VIOINTENSITY vi;
  649.     static KBDINFO ki;
  650.  
  651.     vi.cb = 6;
  652.     vi.type = 2;
  653.     vi.fs = 0;
  654.     VioSetState(&vi, 0);
  655.  
  656.     ki = SaveKbdState;
  657.     ki.fsMask &= ~(KEYBOARD_ECHO_OFF | KEYBOARD_BINARY_MODE);
  658.     ki.fsMask |=  (KEYBOARD_ECHO_ON | KEYBOARD_ASCII_MODE);
  659.     assert(0 == KbdSetStatus(&ki, 0));
  660.  
  661.     ConHideMouse();
  662.  
  663.     signal(SIGBREAK, SIG_DFL);
  664.     signal(SIGINT, SIG_DFL);
  665.  
  666.     return 0;
  667. }
  668.  
  669. int ConContinue() {
  670.     VIOINTENSITY vi;
  671.     static KBDINFO ki;
  672.  
  673.     signal(SIGBREAK, SIG_IGN);
  674.     signal(SIGINT, SIG_IGN);
  675.  
  676.     ki = SaveKbdState;
  677.     ki.fsMask &= ~(KEYBOARD_ECHO_ON | KEYBOARD_ASCII_MODE);
  678.     ki.fsMask |=  (KEYBOARD_ECHO_OFF | KEYBOARD_BINARY_MODE);
  679.     assert(KbdSetStatus (&ki, 0) == 0);
  680.  
  681.     vi.cb = 6;
  682.     vi.type = 2;
  683.     vi.fs = 1;
  684.     VioSetState(&vi, 0);
  685.     ConShowMouse();
  686.     return 0;
  687. }
  688.  
  689. int GetPipeEvent(TEvent *Event) {
  690.     ULONG ulPostCount;
  691.     int i;
  692.  
  693.     Event->What = evNone;
  694.     for (i = 0; i < MAX_PIPES; i++) {
  695.         if (Pipes[i].used == 0) continue;
  696.         if (Pipes[i].notify == 0) continue;
  697.         if (DosResetEventSem(Pipes[i].NewData, &ulPostCount) != 0)
  698.             continue;
  699.         if (ulPostCount > 0) {
  700.             //fprintf(stderr, "Pipe New Data: %d\n", i);
  701.             Event->What = evNotify;
  702.             Event->Msg.View = 0;
  703.             Event->Msg.Model = Pipes[i].notify;
  704.             Event->Msg.Command = cmPipeRead;
  705.             Event->Msg.Param1 = i;
  706.             return 1;
  707.         }
  708.     }
  709.     return 0;
  710. }
  711.  
  712. int ConGetEvent(TEventMask EventMask, TEvent *Event, int WaitTime, int Delete) {
  713.     KBDINFO ki;
  714.  
  715.     if (EventBuf.What != evNone) {
  716.         *Event = EventBuf;
  717.         if (Delete) EventBuf.What = evNone;
  718.         return 0;
  719.     }
  720.     if (MouseEv.What != evNone) {
  721.         *Event = MouseEv;
  722.         if (Delete) MouseEv.What = evNone;
  723.         return 0;
  724.     }
  725.     EventBuf.What = evNone;
  726.     Event->What = evNone;
  727.  
  728.     ki = SaveKbdState;
  729.     ki.fsMask &= ~(KEYBOARD_ECHO_ON | KEYBOARD_ASCII_MODE);
  730.     ki.fsMask |=  (KEYBOARD_ECHO_OFF | KEYBOARD_BINARY_MODE);
  731.     assert(KbdSetStatus (&ki, 0) == 0);
  732.  
  733.     while ((WaitTime == -1) || (WaitTime >= 0)) {
  734.         if ((ReadKbdEvent(Event, WaitTime) == 1) && (EventMask & evKeyboard)) break;
  735.         else if (MousePresent && (ReadMouseEvent(Event, EventMask) == 1) && (EventMask & evMouse)) break;
  736.         else if (GetPipeEvent(Event) == 1) break;
  737.  
  738.         if (WaitTime == 0) return -1;
  739.         DosSleep(5);
  740.         if (WaitTime > 0) {
  741.             WaitTime -= 5;
  742.             if (WaitTime <= 0) return -1;
  743.         }
  744.     }
  745.     if (Event->What != evNone) {
  746.         if (Event->What == evMouseMove) {
  747.             while (ReadMouseEvent(&MouseEv, EventMask) == 1) {
  748.                 if (MouseEv.What == evMouseMove) {
  749.                     *Event = MouseEv;
  750.                     MouseEv.What = evNone;
  751.                 } else break;
  752.             }
  753.         }
  754.         EventBuf = *Event;
  755.         if (Delete) EventBuf.What = evNone;
  756.         return 0;
  757.     }
  758.     return -1;
  759. }
  760.  
  761. static PCell SavedScreen = 0;
  762. static int SavedX, SavedY, SaveCursorPosX, SaveCursorPosY;
  763.  
  764. int SaveScreen() {
  765.     if (SavedScreen)
  766.         free(SavedScreen);
  767.  
  768.     ConQuerySize(&SavedX, &SavedY);
  769.  
  770.     SavedScreen = (PCell) malloc(SavedX * SavedY * sizeof(PCell));
  771.  
  772.     if (SavedScreen)
  773.         ConGetBox(0, 0, SavedX, SavedY, SavedScreen);
  774.     ConQueryCursorPos(&SaveCursorPosX, &SaveCursorPosY);
  775.     return 0;
  776. }
  777.  
  778. int RestoreScreen() {
  779.     if (SavedScreen) {
  780.         ConPutBox(0, 0, SavedX, SavedY, SavedScreen);
  781.         ConSetCursorPos(SaveCursorPosX, SaveCursorPosY);
  782.     }
  783.     return 1;
  784. }
  785.  
  786. GUI::GUI(int &argc, char **argv, int XSize, int YSize) {
  787.     fArgc = argc;
  788.     fArgv = argv;
  789.     ::ConInit(-1, -1);
  790.     SaveScreen();
  791.     ::ConSetSize(XSize, YSize);
  792.     gui = this;
  793. }
  794.  
  795. GUI::~GUI() {
  796.     RestoreScreen();
  797.     ::ConDone();
  798.     gui = 0;
  799. }
  800.  
  801. int GUI::ConSuspend(void) {
  802.     RestoreScreen();
  803.     return ::ConSuspend();
  804. }
  805.  
  806. int GUI::ConContinue(void) {
  807.     SaveScreen();
  808.     return ::ConContinue();
  809. }
  810.  
  811. int GUI::ShowEntryScreen() {
  812.     TEvent E;
  813.  
  814.     ConHideMouse();
  815.     RestoreScreen();
  816.     do { gui->ConGetEvent(evKeyDown, &E, -1, 1, 0); } while (E.What != evKeyDown);
  817.     ConShowMouse();
  818.     if (frames)
  819.         frames->Repaint();
  820.     return 1;
  821. }
  822.  
  823. static int CreatePipeChild(PID &pid, HPIPE &hfPipe, char *Command) {
  824.     static int PCount = 0;
  825.     char szPipe[32];
  826.     char FailBuf[256];
  827.     char *Args;
  828.     int arglen = 0;
  829.     char *Prog;
  830.     RESULTCODES rc_code;
  831.     ULONG ulAction;
  832.     //ULONG ulNew;
  833.     HPIPE hfChildPipe;
  834.     HFILE hfNewStdOut = -1, hfNewStdErr = -1;
  835.     HFILE hfStdOut = 1, hfStdErr = 2;
  836.     int rc;
  837.  
  838.     sprintf(szPipe, "\\PIPE\\FTE%d\\CHILD%d", getpid(), PCount);
  839.     PCount++;
  840.  
  841.     rc = DosCreateNPipe(szPipe, &hfPipe,
  842.                          NP_NOINHERIT | NP_ACCESS_INBOUND,
  843.                          NP_NOWAIT | NP_TYPE_BYTE | NP_READMODE_BYTE | 1,
  844.                          0, 4096, 0);
  845.     if (rc != 0)
  846.         return -1;
  847.  
  848.     rc = DosConnectNPipe (hfPipe);
  849.     if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED) {
  850.         DosClose(hfPipe);
  851.         return -1;
  852.     }
  853.  
  854.     rc = DosSetNPHState (hfPipe, NP_WAIT | NP_READMODE_BYTE);
  855.     if (rc != 0) {
  856.         DosClose(hfPipe);
  857.         return -1;
  858.     }
  859.  
  860.     rc = DosOpen (szPipe, &hfChildPipe, &ulAction, 0,
  861.                   FILE_NORMAL,
  862.                   OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
  863.                   OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYREADWRITE,
  864.                   NULL);
  865.     if (rc != 0) {
  866.         DosClose (hfPipe);
  867.         return -1;
  868.     }
  869.  
  870.     // Duplicate handles
  871.     DosDupHandle(hfStdOut, &hfNewStdOut);
  872.     DosDupHandle(hfStdErr, &hfNewStdErr);
  873.     // Close existing handles for current process
  874.     DosClose(hfStdOut);
  875.     DosClose(hfStdErr);
  876.     // Redirect existing handles to new file
  877.     DosDupHandle(hfChildPipe, &hfStdOut);
  878.     DosDupHandle(hfChildPipe, &hfStdErr);
  879.     // Let started program inherit handles from parent
  880.  
  881.     Prog = getenv("COMSPEC");
  882.  
  883.     Args = (char *)malloc(strlen(Prog) + 1
  884.                           + 3 + strlen(Command) + 1
  885.                           + 1);
  886.     if (Args == NULL) {
  887.         DosClose(hfPipe);
  888.         return -1;
  889.     }
  890.  
  891.     strcpy(Args, Prog);
  892.     arglen = strlen(Args) + 1;
  893.     strcpy(Args + arglen, "/c ");
  894.     arglen += 3;
  895.     strcpy(Args + arglen, Command);
  896.     arglen += strlen(Command) + 1;
  897.     Args[arglen] = '\0';
  898.  
  899.     rc = DosExecPgm(FailBuf, sizeof(FailBuf),
  900.                     EXEC_ASYNCRESULT, // | EXEC_BACKGROUND,
  901.                     Args,
  902.                     0,
  903.                     &rc_code,
  904.                     Prog);
  905.  
  906.     free(Args);
  907.  
  908.     // Get back original handles
  909.     DosDupHandle(hfNewStdOut, &hfStdOut);
  910.     DosDupHandle(hfNewStdErr, &hfStdErr);
  911.     // Close the duplicated handles - no longer needed
  912.     DosClose(hfNewStdOut);
  913.     DosClose(hfNewStdErr);
  914.  
  915.     DosClose(hfChildPipe); // pipe one way, close out write end
  916.  
  917.     if (rc != 0) {
  918.         DosClose(hfPipe);
  919.         return -1;
  920.     }
  921.  
  922.     pid = rc_code.codeTerminate; // get pid when successful
  923.  
  924.     return 0;
  925. }
  926.  
  927. static void _LNK_CONV PipeThread(void *p) {
  928.     GPipe *pipe = (GPipe *)p;
  929.     int rc;
  930.     ULONG ulPostCount;
  931.     ULONG used;
  932.     PID pid;
  933.     HPIPE hfPipe;
  934.     RESULTCODES rc_code;
  935.  
  936.     rc = CreatePipeChild(pid, hfPipe, pipe->Command);
  937.  
  938.     if (rc != 0) {
  939.         //fprintf(stderr, "Failed createpipe");
  940.         DosRequestMutexSem(pipe->Access, SEM_INDEFINITE_WAIT);
  941.         pipe->reading = 0;
  942.         DosPostEventSem(pipe->NewData);
  943.         DosReleaseMutexSem(pipe->Access);
  944.         return;
  945.     }
  946.  
  947.     //fprintf(stderr, "Pipe: Begin: %d %s\n", pipe->id, Args);
  948.     while (1) {
  949.         //fprintf(stderr, "Waiting on pipe\n");
  950.             //fread(pipe->buffer, 1, pipe->buflen, fp);
  951.         rc = DosRead(hfPipe, pipe->buffer, pipe->buflen, &used);
  952.         if (rc < 0)
  953.             used = 0;
  954.  
  955.         DosRequestMutexSem(pipe->Access, SEM_INDEFINITE_WAIT);
  956.         //fprintf(stderr, "Waiting on mutex\n");
  957.         pipe->bufused = used;
  958.         //fprintf(stderr, "Pipe: fread: %d %d\n", pipe->id, pipe->bufused);
  959.         DosResetEventSem(pipe->ResumeRead, &ulPostCount);
  960.         if (pipe->bufused == 0)
  961.             break;
  962.         if (pipe->notify) {
  963.             DosPostEventSem(pipe->NewData);
  964.             pipe->stopped = 0;
  965.         }
  966.         DosReleaseMutexSem(pipe->Access);
  967.         if (pipe->DoTerm)
  968.             break;
  969.         //fprintf(stderr, "Waiting on sem\n");
  970.         DosWaitEventSem(pipe->ResumeRead, SEM_INDEFINITE_WAIT);
  971.         //fprintf(stderr, "Read: Released mutex\n");
  972.         if (pipe->DoTerm)
  973.             break;
  974.     }
  975.     DosClose(hfPipe);
  976.     //fprintf(stderr, "Pipe: pClose: %d\n", pipe->id);
  977.     rc = DosWaitChild(DCWA_PROCESS, DCWW_WAIT,
  978.                       &rc_code,
  979.                       &pid,
  980.                       pid);
  981.     pipe->RetCode = rc_code.codeResult;
  982.             // pclose(fp);
  983.     pipe->reading = 0;
  984.     DosPostEventSem(pipe->NewData);
  985.     DosReleaseMutexSem(pipe->Access);
  986.     //fprintf(stderr, "Read: Released mutex\n");
  987.     return;
  988. }
  989.  
  990. int GUI::OpenPipe(char *Command, EModel *notify) {
  991.     int i;
  992.  
  993.     for (i = 0; i < MAX_PIPES; i++) {
  994.         if (Pipes[i].used == 0) {
  995.             Pipes[i].reading = 1;
  996.             Pipes[i].stopped = 1;
  997.             Pipes[i].id = i;
  998.             Pipes[i].bufused = 0;
  999.             Pipes[i].bufpos = 0;
  1000.             Pipes[i].buflen = PIPE_BUFLEN;
  1001.             Pipes[i].Command = strdup(Command);
  1002.             Pipes[i].notify = notify;
  1003.             Pipes[i].DoTerm = 0;
  1004.             if ((Pipes[i].buffer = (char *)malloc(PIPE_BUFLEN)) == 0)
  1005.                 return -1;
  1006.  
  1007.             if (0 != DosCreateMutexSem(0, &Pipes[i].Access, 0, 0)) {
  1008.                 free(Pipes[i].Command);
  1009.                 free(Pipes[i].buffer);
  1010.                 return -1;
  1011.             }
  1012.  
  1013.             if (0 != DosCreateEventSem(0, &Pipes[i].ResumeRead, 0, 0)) {
  1014.                 free(Pipes[i].Command);
  1015.                 free(Pipes[i].buffer);
  1016.                 DosCloseMutexSem(Pipes[i].Access);
  1017.                 return -1;
  1018.             }
  1019.  
  1020.             if (0 != DosCreateEventSem(0, &Pipes[i].NewData, 0, 0)) {
  1021.                 free(Pipes[i].Command);
  1022.                 free(Pipes[i].buffer);
  1023.                 DosCloseEventSem(Pipes[i].ResumeRead);
  1024.                 DosCloseMutexSem(Pipes[i].Access);
  1025.                 return -1;
  1026.             }
  1027.  
  1028. #if defined(__MT__) || defined(__MULTI__)
  1029.             Pipes[i].tid = _beginthread(PipeThread,
  1030.                                         FAKE_BEGINTHREAD_NULL
  1031.                                         16384, &Pipes[i]);
  1032. #else
  1033.             DosCreateThread(Pipes[i].tid,
  1034.                             (PFNTHREAD)PipeThread,
  1035.                             &Pipes[i],
  1036.                             0, /* immediate */
  1037.                             16384);
  1038. #endif
  1039.             Pipes[i].used = 1;
  1040.             //fprintf(stderr, "Pipe Open: %d\n", i);
  1041.             return i;
  1042.         }
  1043.     }
  1044.     return -1;
  1045. }
  1046.  
  1047. int GUI::SetPipeView(int id, EModel *notify) {
  1048.     if (id < 0 || id > MAX_PIPES)
  1049.         return -1;
  1050.     if (Pipes[id].used == 0)
  1051.         return -1;
  1052.     DosRequestMutexSem(Pipes[id].Access, SEM_INDEFINITE_WAIT);
  1053.     //fprintf(stderr, "Pipe View: %d %08X\n", id, notify);
  1054.     Pipes[id].notify = notify;
  1055.     DosReleaseMutexSem(Pipes[id].Access);
  1056.     return 0;
  1057. }
  1058.  
  1059. int GUI::ReadPipe(int id, void *buffer, int len) {
  1060.     int l;
  1061.     //ULONG ulPostCount;
  1062.  
  1063.     if (id < 0 || id > MAX_PIPES)
  1064.         return -1;
  1065.     if (Pipes[id].used == 0)
  1066.         return -1;
  1067.     //fprintf(stderr, "Read: Waiting on mutex\n");
  1068.     //ConContinue();
  1069.     DosRequestMutexSem(Pipes[id].Access, SEM_INDEFINITE_WAIT);
  1070.     //fprintf(stderr, "Pipe Read: Get %d %d\n", id, len);
  1071.     if (Pipes[id].bufused - Pipes[id].bufpos > 0) {
  1072.         l = len;
  1073.         if (l > Pipes[id].bufused - Pipes[id].bufpos) {
  1074.             l = Pipes[id].bufused - Pipes[id].bufpos;
  1075.         }
  1076.         memcpy(buffer,
  1077.                Pipes[id].buffer + Pipes[id].bufpos,
  1078.                l);
  1079.         Pipes[id].bufpos += l;
  1080.         if (Pipes[id].bufpos == Pipes[id].bufused) {
  1081.             Pipes[id].bufused = 0;
  1082.             Pipes[id].bufpos = 0;
  1083.             //fprintf(stderr, "Pipe Resume Read: %d\n", id);
  1084.             Pipes[id].stopped = 1;
  1085.             //fprintf(stderr, "Read: posting sem\n");
  1086.             DosPostEventSem(Pipes[id].ResumeRead);
  1087.         }
  1088.     } else if (Pipes[id].reading == 0)
  1089.         l = -1;
  1090.     else {
  1091.         l = 0;
  1092. //        DosBeep(200, 200);
  1093.     }
  1094.     //fprintf(stderr, "Pipe Read: Got %d %d\n", id, l);
  1095.     DosReleaseMutexSem(Pipes[id].Access);
  1096.     //fprintf(stderr, "Read: Released mutex\n");
  1097.     return l;
  1098. }
  1099.  
  1100. int GUI::ClosePipe(int id) {
  1101.     if (id < 0 || id > MAX_PIPES)
  1102.         return -1;
  1103.     if (Pipes[id].used == 0)
  1104.         return -1;
  1105.     if (Pipes[id].reading == 1) {
  1106.         Pipes[id].DoTerm = 1;
  1107.         DosPostEventSem(Pipes[id].ResumeRead);
  1108.         DosWaitThread(&Pipes[id].tid, DCWW_WAIT);
  1109.     }
  1110.     free(Pipes[id].buffer);
  1111.     free(Pipes[id].Command);
  1112.     DosCloseEventSem(Pipes[id].NewData);
  1113.     DosCloseEventSem(Pipes[id].ResumeRead);
  1114.     DosCloseMutexSem(Pipes[id].Access);
  1115. //    fprintf(stderr, "Pipe Close: %d\n", id);
  1116.     Pipes[id].used = 0;
  1117.     //ConContinue();
  1118.     return Pipes[id].RetCode;
  1119. }
  1120.  
  1121. int GUI::RunProgram(char *Command) {
  1122.     int rc, W, H, W1, H1;
  1123.  
  1124.     ConQuerySize(&W, &H);
  1125.     ConHideMouse();
  1126.     ConSuspend();
  1127.  
  1128.     if (Command == 0 || *Command == 0)  // empty string = shell
  1129.         Command = getenv(
  1130.                          "COMSPEC"
  1131.                         );
  1132.  
  1133.     rc = system(Command);
  1134.  
  1135.     ConContinue();
  1136.     ConShowMouse();
  1137.     ConQuerySize(&W1, &H1);
  1138.  
  1139.     if (W != W1 || H != H1) {
  1140.         frames->Resize(W1, H1);
  1141.     }
  1142.     frames->Repaint();
  1143.     return rc;
  1144. }
  1145.  
  1146. int ConSetTitle(char *Title, char *STitle) {
  1147. /*    HSWITCH hsw;
  1148.     SWCNTRL sw;
  1149.     HAB hab;
  1150.     PID pid;
  1151.     TID tid;
  1152.  
  1153.     static PVOID Shmem = NULL;
  1154.  
  1155.     if (Shmem == NULL)
  1156.         DosAllocSharedMem(&Shmem, NULL, 4096,
  1157.                           PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_GIVEABLE);
  1158.  
  1159.     strcpy(Shmem, Title);
  1160.  
  1161.     hab = WinInitialize(0);
  1162.  
  1163.     hsw = WinQuerySwitchHandle(NULLHANDLE, getpid());
  1164.  
  1165.     if (WinQuerySwitchEntry(hsw, &sw) != 0)
  1166.         printf("\x7\n");
  1167.     else {
  1168.  
  1169.         strncpy (sw.szSwtitle, Title, MAXNAMEL - 1);
  1170.         sw.szSwtitle[MAXNAMEL-1] = 0;
  1171.  
  1172.         printf("hwnd: %X, hwndIcon: %X, pid: %d\n",
  1173.                sw.hwnd,
  1174.                sw.hwndIcon,
  1175.                sw.idProcess);
  1176.  
  1177.         WinQueryWindowProcess(sw.hwnd, &pid, &tid);
  1178.  
  1179.         DosGiveSharedMem(Shmem, pid, PAG_READ | PAG_WRITE);
  1180.  
  1181.         printf("txt 1: %d\n", WinSetWindowText(sw.hwnd, Shmem));
  1182. //        printf("txt 2: %d\n", WinSetWindowText(Wsw.hwndIcon, Shmem));
  1183.  
  1184.         WinChangeSwitchEntry(hsw, &sw);
  1185.     }
  1186.  
  1187.     WinTerminate(hab);
  1188.   */
  1189.     return 0;
  1190. }
  1191.  
  1192. int ConGetTitle(char *Title, int MaxLen, char *STitle, int SMaxLen) {
  1193.     strcpy(Title, "FTE");
  1194.     strcpy(STitle, "FTE");
  1195.     return 0;
  1196. }
  1197.  
  1198. int ConCursorVisible() {
  1199.     return (CursorVisible == 1);
  1200. }
  1201.  
  1202. int ConPutEvent(TEvent Event) {
  1203.     EventBuf = Event;
  1204.     return 0;
  1205. }
  1206.  
  1207. extern int SevenBit;
  1208.  
  1209. char ConGetDrawChar(int index) {
  1210.     static char tab[] =  "┌┐└┘─│┬├┤┴┼\x1A·─▒░\x1B\x1A";
  1211.     static char tab7[] = "++++-|+++++\x1A.-++#+\x1B\x1A";
  1212.  
  1213.     assert(index >= 0 && index < strlen(tab));
  1214.  
  1215.     if (SevenBit)
  1216.         return tab7[index];
  1217.     else
  1218.         return tab[index];
  1219. }
  1220.