home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / PMEDIT5.ZIP / PMEDIT5.C < prev    next >
C/C++ Source or Header  |  1989-08-29  |  56KB  |  2,039 lines

  1.     
  2. #define INCL_GPI
  3. #define INCL_WIN
  4. #include <OS2.H>
  5. #include <STDIO.H>
  6. #include <PROCESS.H>
  7. #include <IO.H>
  8. #include <STRING.H>
  9. #include <STDLIB.H>
  10.  
  11. #include "PMEDIT5.H"
  12.  
  13. MRESULT EXPENTRY WndProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2);
  14.  
  15. #define LINEBUFSIZ  255
  16. #define ERROPEN     1
  17. #define ERRTOOBIG   2
  18. #define ERRMAXLINES 3
  19. #define ERRALLOC    4
  20.  
  21. void BufInit  (void);
  22. int DeleteChar (SHORT Line, SHORT Column);
  23. void DeleteLine (SHORT Line);
  24. char *ErrorMessage (int ErrorNumber);
  25. PCH GetLineAddr (int Line);
  26. SHORT GetLineLength (int Line);
  27. void GetTempBuf (int Line);
  28.  
  29. int InsertChar (SHORT Line, USHORT Character,SHORT Column, int Overwrite);
  30. void InsertLine (SHORT Line, SHORT Column);
  31. int JoinLine (SHORT Line);
  32. void NewFile (void);
  33. int ReadFile (char *FileName);
  34. void ReleaseFile (void);
  35. void ReleaseTempBuf (int Line);
  36. int SaveFile (char *Filename);
  37. int SearchBuf (char *Findstring, PSHORT Line, PSHORT Col);
  38.  
  39. int LastLine = -1;
  40. HHEAP HHeap = NULL;
  41.  
  42. void ErrorQuit  (char *Message);
  43. char *Extension (char *FileName);
  44. void GetPath (char *Path, unsigned PathLength);
  45. void InitWindow (void);
  46. void Qualify (char *Unqual, char *Qual);
  47. void Quit (int ErrorCode);
  48. void ShowFileName (void);
  49. char *Unqualify (char *Qual);
  50.  
  51. #define PATHLENGTH 128
  52.  
  53. HWND HFrame;
  54. HWND HMenu;
  55. HAB HAncBlk;
  56. HMQ HMesQue;
  57. char Message [64];
  58. char FileName [PATHLENGTH];
  59. char Title [25] = "";
  60. unsigned char Modified = 0;
  61. HWND HClient;
  62.  
  63. void main (int argc, char *argv[])
  64.     {
  65.     int ReadError = 0;
  66.     QMSG QueMess;
  67.     ULONG CtlData = 
  68.         FCF_HORZSCROLL        |
  69.         FCF_MENU            |
  70.         FCF_MINMAX        |
  71.         FCF_SHELLPOSITION    |
  72.         FCF_SIZEBORDER        |
  73.         FCF_SYSMENU        |
  74.         FCF_TASKLIST        |
  75.         FCF_TITLEBAR        |
  76.         FCF_VERTSCROLL;
  77.         
  78.     BufInit  ();
  79.     if (argc < 2)
  80.         {
  81.         FileName [0] = '\0';
  82.         NewFile ();
  83.         }
  84.     else
  85.         {
  86.         Qualify (argv [1],FileName);
  87.         ReadError = ReadFile (FileName);
  88.         }
  89.         
  90.     HAncBlk = WinInitialize (0);
  91.     
  92.     HMesQue = WinCreateMsgQueue (HAncBlk,0);
  93.     
  94.     WinRegisterClass
  95.         (HAncBlk,
  96.         "MAIN",
  97.         WndProc,
  98.         0L,
  99.         0);
  100.     
  101.     HFrame = WinCreateStdWindow
  102.         (HWND_DESKTOP,
  103.         FS_ACCELTABLE |
  104.         WS_VISIBLE,
  105.         &CtlData,
  106.         "MAIN",
  107.         Title,
  108.         0L,
  109.         0,
  110.         ID_FRAME_RESOURCE,
  111.         &HClient);
  112.         
  113.     if (HFrame == NULL)
  114.         ErrorQuit ("WinCreateStdWindow");
  115.     
  116.     ShowFileName ();
  117.     
  118.     HMenu = WinWindowFromID
  119.         (HFrame,
  120.         FID_MENU);
  121.     
  122.     if (ReadError)
  123.         ErrorQuit (ErrorMessage (ReadError));
  124.         
  125.     WinSetFocus
  126.         (HWND_DESKTOP,
  127.         HClient);
  128.     
  129.     while (WinGetMsg
  130.         (HAncBlk,
  131.         &QueMess,
  132.         0,
  133.         0,
  134.         0))
  135.         
  136.         WinDispatchMsg (HAncBlk,&QueMess);
  137.     
  138.     Quit (0);
  139.     
  140.     }
  141.     
  142. MRESULT EXPENTRY Character  (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2);
  143. MRESULT EXPENTRY Command     (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2);
  144. MRESULT EXPENTRY Create      (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2);
  145. MRESULT EXPENTRY Help        (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2);
  146. MRESULT EXPENTRY HScroll     (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2);
  147. MRESULT EXPENTRY InitMenu    (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2);
  148. MRESULT EXPENTRY Paint       (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2);
  149. MRESULT EXPENTRY SetFocus    (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2);
  150. MRESULT EXPENTRY Size        (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2);
  151. MRESULT EXPENTRY VirtKey     (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2);
  152. MRESULT EXPENTRY VScroll     (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2);
  153.  
  154. MRESULT EXPENTRY OpenProc    (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2);
  155. MRESULT EXPENTRY SaveasProc  (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2);
  156. MRESULT EXPENTRY AboutProc   (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2);
  157. MRESULT EXPENTRY FindProc    (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2);
  158. MRESULT EXPENTRY GotoProc   (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2);
  159.  
  160. void NotYet (char *Message);
  161.  
  162. static SHORT xChar;
  163. static SHORT yCharTot;
  164. static SHORT yCharDesc;
  165. static SHORT xWin;
  166. static SHORT yWin;
  167. static HWND HVScroll;
  168. static HWND HHScroll;
  169. static int FirstCol;
  170. static int FirstColMax;
  171. static SHORT TopLine = 0;
  172. static SHORT TopLineMax;
  173. static FATTRS FontAttributes;
  174.  
  175. static SHORT CursorLine = 0;
  176. static SHORT CursorCol = 0;
  177. static SHORT LastCursorLine = 0;
  178.  
  179. static int Insert = 1;
  180. static BlockMarked = 0;
  181. static ClipData = 0;
  182. static FindString [33] = {'\0'};
  183.  
  184. #define ID_COURIER 99L
  185.  
  186. MRESULT EXPENTRY WndProc
  187.     (HWND hwnd,
  188.     USHORT msg,
  189.     MPARAM mp1,
  190.     MPARAM mp2)
  191.     {
  192.     switch (msg)
  193.         {
  194.         case WM_CHAR:
  195.             if (CHARMSG (&msg)->fs & KC_KEYUP)
  196.                 return FALSE;
  197.                 
  198.             else if (CHARMSG (&msg)->fs & KC_CHAR)
  199.                 return Character (hwnd, msg, mp1, mp2);
  200.             else if (CHARMSG (&msg)->fs & KC_VIRTUALKEY)
  201.                 return VirtKey (hwnd, msg, mp1, mp2);
  202.             else
  203.                 return FALSE;
  204.         case WM_COMMAND:
  205.             return Command (hwnd, msg, mp1, mp2);
  206.             
  207.         case WM_CREATE:
  208.             return Create (hwnd, msg, mp1, mp2);
  209.         
  210.         case WM_HELP:
  211.             return Help (hwnd, msg, mp1, mp2);
  212.             
  213.         case WM_HSCROLL:
  214.             return HScroll (hwnd, msg, mp1, mp2);
  215.             
  216.         case WM_INITMENU:
  217.             return InitMenu (hwnd, msg, mp1, mp2);
  218.         
  219.         case WM_PAINT:
  220.             return Paint (hwnd, msg, mp1, mp2);
  221.         
  222.         case WM_SETFOCUS:
  223.             return SetFocus (hwnd, msg, mp1, mp2);
  224.             
  225.         case WM_SIZE:
  226.             return Size (hwnd, msg, mp1, mp2);
  227.         
  228.         case WM_VSCROLL:
  229.             return VScroll (hwnd, msg, mp1, mp2);
  230.             
  231.         default:
  232.             return WinDefWindowProc (hwnd, msg, mp1, mp2);
  233.         }
  234.     }
  235.     
  236. MRESULT EXPENTRY Character (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  237.     {
  238.     register int Col;
  239.     RECTL Rect;
  240.     
  241.     Modified = 1;
  242.     
  243.     if (LastCursorLine != CursorLine)
  244.         {
  245.         ReleaseTempBuf (LastCursorLine);
  246.         GetTempBuf (CursorLine);
  247.         LastCursorLine = CursorLine;
  248.         }
  249.     if (CHARMSG(&msg)->chr == '\b')
  250.         {
  251.         if (CursorCol == 0)
  252.             {
  253.             if (CursorLine == 0)
  254.                 return TRUE;
  255.                 
  256.             WinSendMsg
  257.                 (hwnd,
  258.                 WM_CHAR,
  259.                 MPFROM2SHORT (KC_VIRTUALKEY, 1),
  260.                 MPFROM2SHORT (0, VK_UP));
  261.             WinSendMsg
  262.                 (hwnd,
  263.                 WM_CHAR,
  264.                 MPFROM2SHORT (KC_VIRTUALKEY, 1),
  265.                 MPFROM2SHORT (0, VK_END));
  266.                 
  267.             if (!Insert)
  268.                 return TRUE;
  269.             
  270.             if (!JoinLine (CursorLine + 1))
  271.                 {
  272.                 WinAlarm (HWND_DESKTOP, WA_ERROR);
  273.                 return TRUE;
  274.                 }
  275.             LastCursorLine = CursorLine;
  276.             TopLineMax = max (0,LastLine - yWin / yCharTot + 1);
  277.             
  278.             WinSendMsg
  279.                 (HVScroll,
  280.                 SBM_SETSCROLLBAR,
  281.                 MPFROM2SHORT (TopLine, 0),
  282.                 MPFROM2SHORT (0, TopLineMax));
  283.                 
  284.             WinEnableWindow
  285.                     (HVScroll,
  286.                 TopLineMax ? 1 : 0);
  287.             
  288.             Rect.xLeft = 0;
  289.                 Rect.xRight = xWin;
  290.             Rect.yTop = yWin - (CursorLine - TopLine) * yCharTot;
  291.             Rect.yBottom = 0;
  292.             
  293.             WinInvalidateRect
  294.                 (hwnd,
  295.                 &Rect,
  296.                 FALSE);
  297.                 
  298.             WinUpdateWindow (hwnd);
  299.             return TRUE;
  300.             }        
  301.         WinSendMsg
  302.             (hwnd,
  303.             WM_CHAR,
  304.             MPFROM2SHORT (KC_VIRTUALKEY, 1),
  305.             MPFROM2SHORT (0, VK_LEFT));
  306.         
  307.         if (Insert)
  308.             WinSendMsg
  309.                 (hwnd,
  310.                 WM_CHAR,
  311.                 MPFROM2SHORT (KC_VIRTUALKEY, 1),
  312.                 MPFROM2SHORT (0, VK_DELETE));
  313.                 
  314.         else
  315.             {
  316.             WinSendMsg
  317.                 (hwnd,
  318.                 WM_CHAR,
  319.                 MPFROM2SHORT (KC_CHAR, 1),
  320.                 MPFROM2SHORT (' ',0));
  321.             WinSendMsg
  322.                 (hwnd,
  323.                 WM_CHAR,
  324.                 MPFROM2SHORT (KC_VIRTUALKEY, 1),
  325.                 MPFROM2SHORT (0, VK_LEFT));
  326.             }
  327.             
  328.         return TRUE;
  329.         
  330.         }
  331.         
  332.     if (CHARMSG(&msg)->chr == '\t')
  333.         {
  334.         Col = 5 - CursorCol % 5;
  335.         while (Col--)
  336.             WinSendMsg
  337.                         (hwnd,
  338.                         WM_CHAR,
  339.                         MPFROM2SHORT (KC_CHAR, 1),
  340.                         MPFROM2SHORT (' ',0));
  341.                 return TRUE;
  342.  
  343.         }
  344.     if (CHARMSG (&msg)->chr == '\r')
  345.         {
  346.         if (Insert)
  347.         {
  348.             InsertLine (CursorLine, CursorCol);
  349.  
  350.             TopLineMax = max (0,LastLine - yWin / yCharTot + 1);
  351.  
  352.             WinSendMsg
  353.                 (HVScroll,
  354.                 SBM_SETSCROLLBAR,
  355.                 MPFROM2SHORT (TopLine, 0),
  356.                 MPFROM2SHORT (0, TopLineMax));
  357.  
  358.             WinEnableWindow
  359.                 (HVScroll,
  360.                 TopLineMax ? 1 : 0);
  361.  
  362.             Rect.xLeft = 0;
  363.             Rect.xRight = xWin;
  364.             Rect.yTop = yWin - (CursorLine - TopLine) * yCharTot;
  365.             Rect.yBottom = 0;
  366.  
  367.             WinInvalidateRect
  368.                 (hwnd,
  369.                 &Rect,
  370.                 FALSE);
  371.  
  372.             WinUpdateWindow (hwnd);
  373.  
  374.         }
  375.  
  376.         WinSendMsg
  377.             (hwnd,
  378.             WM_CHAR,
  379.             MPFROM2SHORT (KC_VIRTUALKEY, 1),
  380.             MPFROM2SHORT (0, VK_DOWN));
  381.  
  382.         if (Insert)
  383.             LastCursorLine = CursorLine;
  384.  
  385.         WinSendMsg
  386.             (hwnd,
  387.             WM_CHAR,
  388.             MPFROM2SHORT (KC_VIRTUALKEY, 1),
  389.             MPFROM2SHORT (0, VK_HOME));
  390.  
  391.         return TRUE;
  392.     }
  393.  
  394.     if (!InsertChar
  395.             (CursorLine,
  396.             CHARMSG(&msg) -> chr,
  397.             CursorCol,
  398.             Insert))
  399.             {
  400.                 WinAlarm (HWND_DESKTOP, WA_ERROR);
  401.                 return TRUE;
  402.             }
  403.  
  404.     Rect.xLeft = (CursorCol - FirstCol) * xChar;
  405.     Rect.xRight = min ((GetLineLength (CursorLine) - FirstCol) * xChar, xWin);
  406.     Rect.yBottom = yWin - (CursorLine - TopLine + 1) * yCharTot;
  407.     Rect.yTop = Rect.yBottom + yCharTot;
  408.  
  409.     WinInvalidateRect
  410.         (hwnd,
  411.         &Rect,
  412.         FALSE);
  413.  
  414.     WinUpdateWindow (hwnd);
  415.  
  416.     WinSendMsg
  417.         (hwnd,
  418.         WM_CHAR,
  419.         MPFROM2SHORT (KC_VIRTUALKEY, 1),
  420.         MPFROM2SHORT (0, VK_RIGHT));
  421.  
  422.     return TRUE;
  423. }
  424.  
  425. MRESULT EXPENTRY Command (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  426. {
  427.     USHORT Result;
  428.     USHORT Update = FALSE;
  429.     USHORT Reply;
  430.  
  431.     switch (COMMANDMSG (&msg) -> cmd)
  432.     {
  433.         case ID_NEW:
  434.  
  435.             if (Modified)
  436.             {
  437.                 Reply = WinMessageBox
  438.                     (HWND_DESKTOP,
  439.                     hwnd,
  440.                     "File Unsaved; Save?",
  441.                     "PM Text Editor",
  442.                     0,
  443.                     MB_YESNO |
  444.                     MB_ICONQUESTION);
  445.  
  446.                 if (Reply == MBID_YES)
  447.  
  448.                     while (Modified)
  449.                         WinSendMsg
  450.                             (hwnd,
  451.                             WM_COMMAND,
  452.                             MPFROM2SHORT (ID_SAVE, 0),
  453.                             0L);
  454.  
  455.             }
  456.             ReleaseFile ();
  457.             NewFile ();
  458.             FileName [0] = '\0';
  459.             ShowFileName ();
  460.             Modified = 0;
  461.             InitWindow ();
  462.  
  463.             return FALSE;
  464.  
  465.     case ID_OPEN:
  466.  
  467.         WinDlgBox
  468.             (HWND_DESKTOP,
  469.             hwnd,
  470.             OpenProc,
  471.             NULL,
  472.             ID_OPENDLG,
  473.             NULL);
  474.  
  475.         return FALSE;
  476.  
  477.     case ID_SAVE:
  478.  
  479.         if (FileName [0])
  480.         {
  481.             if (SaveFile (FileName) == FALSE)
  482.  
  483.                 WinMessageBox
  484.                     (HWND_DESKTOP,
  485.                     HFrame,
  486.                     "Error -- Cannot Save File",
  487.                     "PM Text Editor",
  488.                     0,
  489.                     MB_OK |
  490.                     MB_ICONASTERISK);
  491.  
  492.             else
  493.                 Modified = 0;
  494.  
  495.             return FALSE;
  496.         }
  497.     case ID_SAVEAS:
  498.  
  499.         WinDlgBox
  500.             (HWND_DESKTOP,
  501.             hwnd,
  502.             SaveasProc,
  503.             NULL,
  504.             ID_SAVEASDLG,
  505.             NULL);
  506.  
  507.         return FALSE;
  508.  
  509.     case ID_PRINT:
  510.  
  511.         NotYet ("Print File Command");
  512.         return FALSE;
  513.  
  514.     case ID_EXIT:
  515.  
  516.         Quit (0);
  517.         return FALSE;
  518.  
  519.     case ID_ABOUT:
  520.  
  521.         WinDlgBox
  522.             (HWND_DESKTOP,
  523.             hwnd,
  524.             AboutProc,
  525.             NULL,
  526.             ID_ABOUTDLG,
  527.             NULL);
  528.  
  529.         return FALSE;
  530.  
  531.     case ID_CUT:
  532.     case ID_COPY:
  533.     case ID_PASTE:
  534.  
  535.         NotYet ("Clipboard Commands");
  536.         return FALSE;
  537.  
  538.     case ID_FIND:
  539.  
  540.         Result = WinDlgBox
  541.             (HWND_DESKTOP,
  542.             hwnd,
  543.             FindProc,
  544.             NULL,
  545.             ID_FINDDLG,
  546.             NULL);
  547.  
  548.         if (Result)
  549.         {
  550.  
  551.             WinInvalidateRect
  552.                 (hwnd,
  553.                 NULL,
  554.                 FALSE);
  555.  
  556.             WinUpdateWindow (hwnd);
  557.  
  558.             WinSendMsg
  559.                 (HHScroll,
  560.                 SBM_SETPOS,
  561.                 MPFROM2SHORT (FirstCol, 0),
  562.                 0);
  563.  
  564.             WinSendMsg
  565.                 (HVScroll,
  566.                 SBM_SETPOS,
  567.                 MPFROM2SHORT (TopLine, 0),
  568.                 0);
  569.         }
  570.         return FALSE;
  571.  
  572.     case ID_FINDNEXT:
  573.  
  574.         if (SearchBuf (FindString, &CursorLine, &CursorCol) == FALSE)
  575.         {
  576.             WinMessageBox
  577.                 (HWND_DESKTOP,
  578.                 HFrame,
  579.                 "String not found",
  580.                 "PM Test Editor",
  581.                 0,
  582.                 MB_OK  |
  583.                 MB_ICONASTERISK);
  584.  
  585.             return FALSE;
  586.         }
  587.  
  588.         if (CursorLine < TopLine || CursorLine >= TopLine + yWin/yCharTot)
  589.         {
  590.             TopLine = max (0,CursorLine - (yWin/yCharTot)/2);
  591.             TopLine = min (TopLine,TopLineMax);
  592.             Update = TRUE;
  593.         }
  594.  
  595.         if (CursorCol < FirstCol || CursorCol >= FirstCol + xWin/xChar)
  596.         {
  597.             FirstCol = max (0,CursorCol - (xWin/xChar)/2);
  598.             FirstCol = min (FirstCol,FirstColMax);
  599.             Update = TRUE;
  600.         }
  601.  
  602.         if (Update)
  603.         {
  604.             WinInvalidateRect
  605.                 (hwnd,
  606.                 NULL,
  607.                 FALSE);
  608.  
  609.             WinUpdateWindow (hwnd);
  610.  
  611.             WinSendMsg
  612.                 (HHScroll,
  613.                 SBM_SETPOS,
  614.                 MPFROM2SHORT (FirstCol, 0),
  615.                 0);
  616.  
  617.             WinSendMsg
  618.                 (HVScroll,
  619.                 SBM_SETPOS,
  620.                 MPFROM2SHORT (TopLine, 0),
  621.                 0);
  622.  
  623.         }
  624.  
  625.         WinCreateCursor
  626.             (hwnd,
  627.             (CursorCol - FirstCol) * xChar,
  628.             yWin - (CursorLine - TopLine + 1) * yCharTot,
  629.             0,
  630.             0,
  631.             CURSOR_SETPOS,
  632.             NULL);
  633.         return FALSE;
  634.  
  635.     case ID_GOTOLINE:
  636.  
  637.         Result = WinDlgBox
  638.             (HWND_DESKTOP,
  639.             hwnd,
  640.             GotoProc,
  641.             NULL,
  642.             ID_GOTODLG,
  643.             NULL);
  644.  
  645.         if (Result)
  646.         {
  647.             WinInvalidateRect
  648.                 (hwnd,
  649.                 NULL,
  650.                 FALSE);
  651.  
  652.             WinUpdateWindow (hwnd);
  653.  
  654.             WinSendMsg
  655.                 (HHScroll,
  656.                 SBM_SETPOS,
  657.                 MPFROM2SHORT (FirstCol, 0),
  658.                 0);
  659.            WinSendMsg (HVScroll, SBM_SETPOS, MPFROM2SHORT (TopLine, 0), 0);
  660.  
  661.         }
  662.  
  663.         return FALSE;
  664.  
  665.     case ID_INSERT:
  666.  
  667.         Insert ^= 1;
  668.         return FALSE;
  669.  
  670.     default:
  671.  
  672.         return FALSE;
  673.     }
  674. }
  675.  
  676. MRESULT EXPENTRY Create (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  677. {
  678.     HPS HPresSpace;
  679.     FONTMETRICS Metrics;
  680.     LONG NumberStructs = 1;
  681.  
  682.     GpiLoadFonts
  683.         (HAncBlk,
  684.         "\\OS2\\DLL\\COURIER.FON");
  685.  
  686.     HPresSpace = WinGetPS (hwnd);
  687.  
  688.     GpiQueryFonts
  689.         (HPresSpace,
  690.         QF_PRIVATE,
  691.         "Courier",
  692.         &NumberStructs,
  693.         (long)sizeof (FONTMETRICS),
  694.         &Metrics);
  695.  
  696.     xChar   =  (SHORT)Metrics.lAveCharWidth;
  697.     yCharTot = (SHORT)Metrics.lMaxBaselineExt;
  698.     yCharDesc = (SHORT)Metrics.lMaxDescender;
  699.  
  700.     FontAttributes.usRecordLength = sizeof (FontAttributes);
  701.     FontAttributes.fsSelection = Metrics.fsSelection;
  702.     FontAttributes.lMatch = Metrics.lMatch;
  703.     strcpy (FontAttributes.szFacename,Metrics.szFacename);
  704.     FontAttributes.idRegistry = Metrics.idRegistry;
  705.     FontAttributes.usCodePage = Metrics.usCodePage;
  706.     FontAttributes.lMaxBaselineExt = Metrics.lMaxBaselineExt;
  707.     FontAttributes.lAveCharWidth = Metrics.lAveCharWidth;
  708.     FontAttributes.fsType = FATTR_TYPE_FIXED;
  709.     FontAttributes.fsFontUse = 0;
  710.  
  711.     WinReleasePS (HPresSpace);
  712.  
  713.     HHScroll = WinWindowFromID
  714.         (WinQueryWindow (hwnd, QW_PARENT,FALSE), FID_HORZSCROLL);
  715.  
  716.     HVScroll = WinWindowFromID
  717.         (WinQueryWindow (hwnd, QW_PARENT,FALSE),
  718.         FID_VERTSCROLL);
  719.  
  720.     return FALSE;
  721. }
  722.  
  723. MRESULT EXPENTRY Help (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  724. {
  725.     NotYet ("Help Window");
  726.     return FALSE;
  727. }
  728.  
  729. MRESULT EXPENTRY HScroll (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  730. {
  731.     SHORT Delta;
  732.  
  733.     switch (SHORT2FROMMP (mp2))
  734.     {
  735.         case SB_LINELEFT:
  736.             Delta = -1;
  737.             break;
  738.         case SB_LINERIGHT:
  739.             Delta = 1;
  740.             break;
  741.         case SB_PAGELEFT:
  742.             Delta = -6;
  743.             break;
  744.         case SB_PAGERIGHT:
  745.             Delta = 6;
  746.             break;
  747.         case SB_SLIDERPOSITION:
  748.             Delta = SHORT1FROMMP (mp2) - FirstCol;
  749.             break;
  750.         default:
  751.             Delta = 0;
  752.             break;
  753.         }
  754.     Delta = max (-FirstCol, min(Delta,FirstColMax - FirstCol));
  755.  
  756.     if (Delta)
  757.     {
  758.         FirstCol += Delta;
  759.         CursorCol += Delta;
  760.  
  761.         WinShowCursor
  762.             (hwnd,
  763.             FALSE);
  764.  
  765.         WinScrollWindow
  766.             (hwnd,
  767.             -Delta * xChar,
  768.             0,
  769.             0,
  770.             0,
  771.             0,
  772.             0,
  773.             SW_INVALIDATERGN);
  774.  
  775.         WinUpdateWindow
  776.             (hwnd);
  777.  
  778.         WinSendMsg
  779.             (HHScroll,
  780.             SBM_SETPOS,
  781.             MPFROM2SHORT (FirstCol,0),
  782.             0);
  783.  
  784.         WinCreateCursor
  785.             (hwnd,
  786.             (CursorCol - FirstCol) * xChar,
  787.             yWin - (CursorLine - TopLine + 1) * yCharTot,
  788.             0,
  789.             0,
  790.             CURSOR_SETPOS,
  791.             NULL);
  792.  
  793.         WinShowCursor
  794.             (hwnd,
  795.             TRUE);
  796.         }
  797.     return FALSE;
  798. }
  799.  
  800. MRESULT EXPENTRY InitMenu (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  801. {
  802.     switch (SHORT1FROMMP (mp1))
  803.     {
  804.         case ID_EDIT:
  805.  
  806.             WinSendMsg (HMenu, MM_SETITEMATTR, MPFROM2SHORT (ID_CUT, TRUE),
  807.                 MPFROM2SHORT (MIA_DISABLED, BlockMarked ? 0 : MIA_DISABLED));
  808.  
  809.             WinSendMsg (HMenu, MM_SETITEMATTR, MPFROM2SHORT (ID_COPY,TRUE),
  810.                 MPFROM2SHORT (MIA_DISABLED, BlockMarked ? 0 : MIA_DISABLED));
  811.                     
  812.             WinSendMsg (HMenu, MM_SETITEMATTR,MPFROM2SHORT (ID_PASTE, TRUE),
  813.                  MPFROM2SHORT (MIA_DISABLED, ClipData ? 0 :MIA_DISABLED));
  814.  
  815.             return FALSE;
  816.  
  817.         case ID_SEARCH:
  818.  
  819.             WinSendMsg (HMenu, MM_SETITEMATTR, MPFROM2SHORT (ID_FINDNEXT, TRUE),
  820.                 MPFROM2SHORT (MIA_DISABLED, FindString [0] ? 0 : MIA_DISABLED));
  821.  
  822.             return FALSE;
  823.  
  824.         case ID_OPTIONS:
  825.  
  826.             WinSendMsg (HMenu, MM_SETITEMTEXT, MPFROM2SHORT (ID_INSERT,0),
  827.                 Insert ? (MPARAM)(PCH)"Overwrite Mode\tIns"
  828.                         : (MPARAM)(PCH)"Insert Mode\tIns");
  829.             return FALSE;
  830.  
  831.         default:
  832.             return FALSE;
  833.         }
  834.     }
  835.  
  836.  
  837. MRESULT EXPENTRY Paint (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  838. {
  839.     register int Line;
  840.     HPS HPresSpace;
  841.     RECTL Rect;
  842.     SHORT StartLine;
  843.     SHORT StopLine;
  844.     POINTL Start;
  845.     SHORT LineLength;
  846.  
  847.     HPresSpace = WinBeginPaint (hwnd, 0, &Rect);
  848.  
  849.     GpiCreateLogFont (HPresSpace, (PSTR8)NULL, ID_COURIER, &FontAttributes);
  850.  
  851.     GpiSetCharSet (HPresSpace, ID_COURIER);
  852.  
  853.     WinFillRect (HPresSpace, &Rect, CLR_WHITE);
  854.     GpiSetColor (HPresSpace, CLR_BLACK);
  855.     StartLine = TopLine + (yWin - (SHORT)Rect.yTop) / yCharTot;
  856.     StopLine = min(LastLine, TopLine + (yWin - (SHORT)Rect.yBottom) / yCharTot);
  857.     Start.y = yWin - yCharTot * (StartLine - TopLine + 1) + yCharDesc;
  858.     Start.x = xChar * (-FirstCol);
  859.     for (Line = StartLine; Line <= StopLine; ++Line, Start.y -= yCharTot)
  860.     {
  861.         if ((LineLength = GetLineLength (Line)) == 0)
  862.             continue;
  863.         GpiCharStringAt (HPresSpace, &Start, (LONG)LineLength, 
  864.             GetLineAddr (Line));
  865.     }
  866.     WinEndPaint (HPresSpace);
  867.  
  868.     return FALSE;
  869. }
  870.  
  871. MRESULT EXPENTRY SetFocus (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  872. {
  873.     if (LONGFROMMP (mp2))
  874.     {
  875.         WinCreateCursor
  876.             (hwnd,
  877.             (CursorCol - FirstCol) * xChar,
  878.             yWin - (CursorLine - TopLine + 1) * yCharTot,
  879.             0,
  880.             yCharTot,
  881.             CURSOR_SOLID |
  882.             CURSOR_FLASH,
  883.             NULL);
  884.  
  885.         WinShowCursor (hwnd, TRUE);
  886.     }
  887.     else
  888.         WinDestroyCursor (hwnd);
  889.     return FALSE;
  890. }
  891.  
  892. MRESULT EXPENTRY Size (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  893. {
  894.     int Update = 0;
  895.  
  896.     yWin = SHORT2FROMMP (mp2);
  897.     xWin = SHORT1FROMMP (mp2);
  898.  
  899.     if (CursorLine >= TopLine + yWin / yCharTot)
  900.     {
  901.         TopLine = CursorLine - yWin / yCharTot + 1;
  902.         Update = 1;
  903.     }
  904.     if (CursorCol >= FirstCol + xWin / xChar)
  905.     {
  906.         FirstCol = CursorCol - xWin / xChar + 1;
  907.         Update = 1;
  908.     }
  909.     if (Update)
  910.         WinInvalidateRect (hwnd,0,FALSE);
  911.     if (hwnd == WinQueryFocus (HWND_DESKTOP,FALSE))
  912.     {
  913.         WinDestroyCursor (hwnd);
  914.         WinCreateCursor (hwnd,
  915.             (CursorCol - FirstCol) * xChar,
  916.             yWin - (CursorLine - TopLine + 1) * yCharTot,
  917.             0,
  918.             yCharTot,
  919.             CURSOR_SOLID |
  920.             CURSOR_FLASH,
  921.             NULL);
  922.         WinShowCursor
  923.             (hwnd, TRUE);
  924.         }
  925.     TopLineMax = max (0,LastLine - yWin / yCharTot + 1);
  926.     TopLine = min (TopLine, TopLineMax);
  927.  
  928.     WinSendMsg
  929.         (HVScroll,
  930.         SBM_SETSCROLLBAR,
  931.         MPFROM2SHORT (TopLine, 0),
  932.         MPFROM2SHORT (0, TopLineMax));
  933.  
  934.     WinEnableWindow
  935.         (HVScroll, TopLineMax ? TRUE : FALSE);
  936.  
  937.     FirstColMax = LINEBUFSIZ - 2 - xWin / xChar;
  938.     FirstCol = min (FirstCol, FirstColMax);
  939.  
  940.     WinSendMsg
  941.         (HHScroll,
  942.         SBM_SETSCROLLBAR,
  943.         MPFROM2SHORT (FirstCol, 0),
  944.         MPFROM2SHORT (0, FirstColMax));
  945.     return FALSE;
  946. }
  947.  
  948. MRESULT EXPENTRY VirtKey (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  949. {
  950.     RECTL Rect;
  951.     SHORT NewFirstCol;
  952.     SHORT NewCursorCol;
  953.     int Update;
  954.  
  955.     switch (CHARMSG (&msg) -> vkey)
  956.     {
  957.         case VK_UP:
  958.             if (CursorLine == TopLine)
  959.             {
  960.                 WinSendMsg (hwnd, WM_VSCROLL, 0L, MPFROM2SHORT (0,SB_LINEUP));
  961.                 return TRUE;
  962.             }
  963.             else
  964.                 --CursorLine;
  965.             break;
  966.  
  967.         case VK_DOWN:
  968.  
  969.             if (CursorLine == LastLine)
  970.                 return TRUE;
  971.  
  972.             else if (CursorLine == TopLine + yWin / yCharTot - 1)
  973.             {
  974.                 WinSendMsg (hwnd, WM_VSCROLL,0L,MPFROM2SHORT (0, SB_LINEDOWN));
  975.                 return TRUE;
  976.             }
  977.             else
  978.                 ++CursorLine;
  979.             break;
  980.  
  981.         case VK_LEFT:
  982.  
  983.             if (CursorCol == FirstCol)
  984.             {
  985.                 WinSendMsg (hwnd, WM_HSCROLL,0L,MPFROM2SHORT (0,SB_LINELEFT));
  986.                 return TRUE;
  987.             }
  988.             else
  989.                 --CursorCol;
  990.             break;
  991.  
  992.         case VK_RIGHT:
  993.  
  994.             if (CursorCol == FirstCol + xWin / xChar - 1)
  995.             {
  996.                 WinSendMsg (hwnd, WM_HSCROLL, 0L, MPFROM2SHORT (0,SB_LINERIGHT));
  997.                 return TRUE;
  998.             }
  999.             else
  1000.                 ++CursorCol;
  1001.             break;
  1002.         case VK_PAGEUP:
  1003.  
  1004.             WinSendMsg (hwnd, WM_VSCROLL,0L,MPFROM2SHORT (0,SB_PAGEUP));
  1005.             return TRUE;
  1006.         case VK_PAGEDOWN:
  1007.  
  1008.             WinSendMsg (hwnd, WM_VSCROLL,0L,MPFROM2SHORT (0,SB_PAGEDOWN));
  1009.             return TRUE;
  1010.  
  1011.         case VK_HOME:
  1012.  
  1013.             if (FirstCol != 0)
  1014.             {
  1015.                 WinSendMsg (hwnd, WM_HSCROLL,0L,MPFROM2SHORT (0,SB_SLIDERPOSITION));
  1016.             }
  1017.             CursorCol = 0;
  1018.  
  1019.             break;
  1020.  
  1021.         case VK_END:
  1022.  
  1023.             NewCursorCol = (int)GetLineLength (CursorLine);
  1024.             Update = 0;
  1025.             if (NewCursorCol > FirstCol + xWin / xChar - 1)
  1026.             {
  1027.                 NewFirstCol = NewCursorCol - xWin / xChar + 1;
  1028.                 Update = 1;
  1029.             }
  1030.             else if (NewCursorCol < FirstCol)
  1031.             {
  1032.                 NewFirstCol = NewCursorCol;
  1033.                 Update = 1;
  1034.             }
  1035.             if (Update)
  1036.                 WinSendMsg (hwnd, WM_HSCROLL,0L,MPFROM2SHORT 
  1037.                     (NewFirstCol,SB_SLIDERPOSITION));
  1038.             CursorCol = NewCursorCol;
  1039.             break;
  1040.             
  1041.         case VK_DELETE:
  1042.             Modified = 1;
  1043.             if (LastCursorLine != CursorLine)
  1044.             {
  1045.                 ReleaseTempBuf (LastCursorLine);
  1046.                 GetTempBuf (CursorLine);
  1047.                 LastCursorLine = CursorLine;
  1048.             }
  1049.             if (DeleteChar (CursorLine, CursorCol))
  1050.             {
  1051.                 Rect.xLeft = (CursorCol - FirstCol) * xChar;
  1052.                 Rect.xRight = min ((GetLineLength(CursorLine) + 1 -
  1053.                                     FirstCol) * xChar,xWin);
  1054.                 Rect.yBottom = yWin - (CursorLine - TopLine + 1) * yCharTot;
  1055.                 Rect.yTop = Rect.yBottom + yCharTot;
  1056.                 WinInvalidateRect (hwnd, &Rect, FALSE);
  1057.                 WinUpdateWindow (hwnd);
  1058.             }
  1059.             return TRUE;
  1060.         case VK_F9:
  1061.             Modified = 1;
  1062.             if (LastCursorLine != CursorLine)
  1063.             {
  1064.                 ReleaseTempBuf (LastCursorLine);
  1065.                 GetTempBuf (CursorLine);
  1066.                 LastCursorLine = CursorLine;
  1067.             }
  1068.             DeleteLine (CursorLine);
  1069.             TopLineMax = max (0, LastLine - yWin / yCharTot + 1);
  1070.             WinSendMsg (HVScroll, SBM_SETSCROLLBAR,MPFROM2SHORT (TopLine, 0),
  1071.                         MPFROM2SHORT (0, TopLineMax));
  1072.             WinEnableWindow (HVScroll, TopLineMax ? 1 : 0);
  1073.             Rect.xLeft = 0;
  1074.             Rect.xRight = xWin;
  1075.             Rect.yTop = yWin - (CursorLine - TopLine) * yCharTot;
  1076.             Rect.yBottom = 0;
  1077.             WinInvalidateRect (hwnd, &Rect, FALSE);
  1078.             WinUpdateWindow (hwnd);
  1079.             return TRUE;
  1080.         default:
  1081.             return FALSE;
  1082.         }
  1083.     WinCreateCursor
  1084.         (hwnd,
  1085.         (CursorCol - FirstCol) * xChar,
  1086.         yWin - (CursorLine - TopLine + 1) * yCharTot,
  1087.         0,
  1088.         0,
  1089.         CURSOR_SETPOS,
  1090.         NULL);
  1091.     return TRUE;
  1092. }
  1093.  
  1094. MRESULT EXPENTRY VScroll (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  1095. {
  1096.     SHORT Delta;
  1097.     switch (SHORT2FROMMP (mp2))
  1098.     {
  1099.         case SB_LINEUP:
  1100.             Delta = -1;
  1101.             break;
  1102.         case SB_LINEDOWN:
  1103.             Delta = 1;
  1104.             break;
  1105.         case SB_PAGEUP:
  1106.             Delta = -yWin / yCharTot;
  1107.             break;
  1108.         case SB_PAGEDOWN:
  1109.             Delta = yWin / yCharTot;
  1110.             break;
  1111.         case SB_SLIDERPOSITION:
  1112.             Delta = SHORT1FROMMP (mp2) - TopLine;
  1113.             break;
  1114.         default:
  1115.             Delta = 0;
  1116.             break;
  1117.         }
  1118.         Delta = max (-TopLine, min(Delta,TopLineMax - TopLine));
  1119.         if (Delta)
  1120.         {
  1121.             TopLine += Delta;
  1122.             CursorLine += Delta;
  1123.             WinShowCursor (hwnd, FALSE);
  1124.             WinScrollWindow
  1125.                 (hwnd,
  1126.                 0,
  1127.                 yCharTot * Delta,
  1128.                 0,
  1129.                 0,
  1130.                 0,
  1131.                 0,
  1132.                 SW_INVALIDATERGN);
  1133.             WinUpdateWindow (hwnd);
  1134.             WinSendMsg (HVScroll, SBM_SETPOS,MPFROM2SHORT (TopLine,0), 0);
  1135.             WinCreateCursor
  1136.                 (hwnd,
  1137.                 (CursorCol - FirstCol) * xChar,
  1138.                 yWin - (CursorLine - TopLine + 1) * yCharTot,
  1139.                 0,
  1140.                 0,
  1141.                 CURSOR_SETPOS,
  1142.                 NULL);
  1143.             WinShowCursor (hwnd, TRUE);
  1144.         }
  1145.         return FALSE;
  1146. }
  1147.  
  1148. MRESULT EXPENTRY AboutProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  1149. {
  1150.     switch (msg)
  1151.     {
  1152.         case WM_COMMAND:
  1153.  
  1154.             switch (COMMANDMSG(&msg)->cmd)
  1155.             {
  1156.                 case DID_OK:
  1157.                 case DID_CANCEL:
  1158.                     WinDismissDlg(hwnd,TRUE);
  1159.                     return FALSE;
  1160.  
  1161.                 default:
  1162.                     return FALSE;
  1163.             }
  1164.         default:
  1165.             return WinDefDlgProc (hwnd, msg, mp1, mp2);
  1166.     }
  1167. }
  1168.  
  1169. MRESULT EXPENTRY FindProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  1170. {
  1171.     char Buffer [2];
  1172.     USHORT Update = FALSE;
  1173.  
  1174.     switch (msg)
  1175.     {
  1176.         case WM_COMMAND:
  1177.             switch (COMMANDMSG(&msg)->cmd)
  1178.             {
  1179.                 case DID_OK:
  1180.  
  1181.                 WinQueryWindowText (WinWindowFromID (hwnd, ID_FINDEDIT),
  1182.                     sizeof (FindString),
  1183.                     FindString);
  1184.  
  1185.                 if (FindString [0] == '\0')
  1186.                     return FALSE;
  1187.  
  1188.                 if (SearchBuf (FindString, &CursorLine, &CursorCol) == FALSE)
  1189.                 {
  1190.                     WinMessageBox
  1191.                         (HWND_DESKTOP,
  1192.                         hwnd,
  1193.                         "String not found",
  1194.                         "PM Text Editor",
  1195.                         0,
  1196.                         MB_OK |
  1197.                         MB_ICONASTERISK);
  1198.                     WinDismissDlg (hwnd, FALSE);
  1199.                     return FALSE;
  1200.                 }
  1201.                 if (CursorLine < TopLine || CursorLine >= TopLine +
  1202.                     yWin/yCharTot)
  1203.                 {
  1204.                     TopLine = max (0,CursorLine - (yWin/yCharTot)/2);
  1205.                     TopLine = min (TopLine, TopLineMax);
  1206.                     Update = TRUE;
  1207.                 }
  1208.                 if (CursorCol < FirstCol || CursorCol >= FirstCol + xWin / xChar)
  1209.                 {
  1210.                     FirstCol = max (0, CursorCol - (xWin/xChar)/2);
  1211.                     FirstCol = min (FirstCol,FirstColMax);
  1212.                     Update = TRUE;
  1213.                 }
  1214.                 WinDismissDlg (hwnd,FALSE);
  1215.                 return FALSE;
  1216.             case DID_CANCEL:
  1217.                 WinDismissDlg (hwnd,FALSE);
  1218.                 return FALSE;
  1219.             default:
  1220.                 return FALSE;
  1221.             }
  1222.         case WM_CONTROL:
  1223.  
  1224.             switch (SHORT1FROMMP (mp1))
  1225.             {
  1226.                 case ID_FINDEDIT:
  1227.  
  1228.                     switch (SHORT2FROMMP (mp1))
  1229.                     {
  1230.                         case EN_CHANGE:
  1231.                             WinQueryWindowText ((HWND) mp2, 2, Buffer);
  1232.                             WinEnableWindow (WinWindowFromID (hwnd, DID_OK),
  1233.                                             Buffer [0]);
  1234.                             return FALSE;
  1235.                         default:
  1236.                             return FALSE;
  1237.                     }
  1238.                 default:
  1239.                     return FALSE;
  1240.             }
  1241.         case WM_INITDLG:
  1242.             WinSetWindowText (WinWindowFromID (hwnd,ID_FINDEDIT), FindString);
  1243.         default:
  1244.             return WinDefDlgProc (hwnd, msg, mp1, mp2);
  1245.         }
  1246. }
  1247.  
  1248. MRESULT EXPENTRY GotoProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  1249. {
  1250.     char NumberBuf [33];
  1251.     char Buffer [2];
  1252.     SHORT LineNumber;
  1253.  
  1254.     switch (msg)
  1255.     {
  1256.         case WM_COMMAND:
  1257.  
  1258.             switch (COMMANDMSG (&msg)->cmd)
  1259.             {
  1260.                 case DID_OK:
  1261.  
  1262.                     WinQueryWindowText (WinWindowFromID(hwnd, ID_GOTOEDIT),
  1263.                         sizeof (NumberBuf),
  1264.                         NumberBuf);
  1265.                     LineNumber = atoi (NumberBuf);
  1266.                     if (LineNumber <= 0)
  1267.                         return FALSE;
  1268.  
  1269.                     --LineNumber;
  1270.                     CursorLine = min(LastLine,LineNumber);
  1271.                     TopLine = max (0,CursorLine - (yWin/yCharTot)/2);
  1272.                     TopLine = min(TopLine,TopLineMax);
  1273.                     CursorCol = FirstCol = 0;
  1274.                     WinDismissDlg (hwnd, TRUE);
  1275.                     return FALSE;
  1276.                 case DID_CANCEL:
  1277.                     WinDismissDlg (hwnd,FALSE);
  1278.                     return FALSE;
  1279.                 default:
  1280.                     return FALSE;
  1281.                 }
  1282.  
  1283.         case WM_CONTROL:
  1284.             switch (SHORT1FROMMP (mp1))
  1285.             {
  1286.                 case ID_GOTOEDIT:
  1287.                     switch (SHORT2FROMMP (mp1))
  1288.                     {
  1289.                         case EN_CHANGE:
  1290.                             WinQueryWindowText ((HWND) mp2, 2, Buffer);
  1291.                             WinEnableWindow (WinWindowFromID (hwnd, DID_OK),
  1292.                                 Buffer [0]);
  1293.                             return FALSE;
  1294.                         default:
  1295.                             return FALSE;
  1296.                     }
  1297.                 default:
  1298.                      return FALSE;
  1299.                 }
  1300.            case WM_INITDLG:
  1301.                     WinEnableWindow (WinWindowFromID (hwnd, DID_OK), FALSE);
  1302.                     return FALSE;
  1303.            default:
  1304.                return WinDefDlgProc (hwnd, msg, mp1, mp2);
  1305.             }
  1306. }
  1307.  
  1308. VOID InitDlg (HWND hwnd);
  1309.  
  1310. MRESULT EXPENTRY OpenProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  1311. {
  1312.     SHORT SelectIndex;
  1313.     char Buffer [16];
  1314.     static char FilePath [PATHLENGTH];
  1315.     USHORT Reply;
  1316.  
  1317.     switch (msg)
  1318.     {
  1319.         case WM_COMMAND:
  1320.  
  1321.             switch (COMMANDMSG(&msg)->cmd)
  1322.             {
  1323.                 case DID_OK:
  1324.                     WinQueryWindowText (WinWindowFromID (hwnd, ID_OPENEDIT),
  1325.                         sizeof (FilePath),
  1326.                         FilePath);
  1327.  
  1328.                     if (FilePath [0])
  1329.                     {
  1330.                         if (Modified)
  1331.                         {
  1332.                             Reply = WinMessageBox (HWND_DESKTOP,
  1333.                                 hwnd,
  1334.                                 "File Unsaved; Save?",
  1335.                                 "PM Text Editor",
  1336.                                 0,
  1337.                                 MB_YESNO  |
  1338.                                 MB_ICONQUESTION);
  1339.                             if (Reply == MBID_YES)
  1340.                                 while (Modified)
  1341.                                     WinSendMsg (HClient, WM_COMMAND,
  1342.                                         MPFROM2SHORT (ID_SAVE, 0),
  1343.                                         0L);
  1344.                         }
  1345.                     ReleaseFile ();
  1346.                     if (ReadFile (FilePath))
  1347.                     {
  1348.                         WinMessageBox (HWND_DESKTOP, hwnd,
  1349.                             "Error -- Cannot Read File",
  1350.                             "PM Text Editor",
  1351.                             0,
  1352.                             MB_OK  |
  1353.                             MB_ICONASTERISK);
  1354.                         FileName [0] = '\0';
  1355.                         NewFile ();
  1356.                     }
  1357.                     else
  1358.                         Qualify (FilePath, FileName);
  1359.                     ShowFileName ();
  1360.                     Modified = 0;
  1361.                     InitWindow ();
  1362.  
  1363.                     WinDismissDlg (hwnd, TRUE);
  1364.                     return FALSE;
  1365.                 }
  1366.                 return FALSE;
  1367.             case DID_CANCEL:
  1368.                 WinDismissDlg (hwnd, TRUE);
  1369.                 return FALSE;
  1370.             default:
  1371.                 return FALSE;
  1372.             }
  1373.         case WM_CONTROL:
  1374.  
  1375.             switch (SHORT1FROMMP (mp1))
  1376.             {
  1377.                 case ID_OPENEDIT:
  1378.  
  1379.                     switch (SHORT2FROMMP (mp1))
  1380.                     {
  1381.                         case EN_CHANGE:
  1382.                             WinQueryWindowText ((HWND) mp2, 2, Buffer);
  1383.                             WinEnableWindow (WinWindowFromID(hwnd, DID_OK),
  1384.                                 Buffer [0]);
  1385.                             return FALSE;
  1386.                         default:
  1387.                             return FALSE;
  1388.                     }
  1389.                 case ID_OPENLIST:
  1390.                     SelectIndex = (SHORT) WinSendDlgItemMsg
  1391.                         (hwnd,ID_OPENLIST,
  1392.                         LM_QUERYSELECTION,
  1393.                         0L,
  1394.                         0L);
  1395.                     WinSendDlgItemMsg (hwnd,ID_OPENLIST,LM_QUERYITEMTEXT,
  1396.                         MPFROM2SHORT (SelectIndex, sizeof (Buffer)),
  1397.                             MPFROMP (Buffer));
  1398.                     switch (SHORT2FROMMP (mp1))
  1399.                     {
  1400.                         case LN_ENTER:
  1401.                             if (Buffer [0] == '[' && Buffer [1] == '-')
  1402.                             {
  1403.                                 DosSelectDisk (Buffer [2] - 64);
  1404.                                 InitDlg (hwnd);
  1405.                             }
  1406.                             else if (Buffer [0] == '[')
  1407.                             {
  1408.                                 Buffer [strlen (Buffer) - 1] = '\0';
  1409.                                 DosChDir (Buffer + 1, 0L);
  1410.                                 InitDlg (hwnd);
  1411.                             }
  1412.                             else if (Buffer [0])
  1413.                             {
  1414.                                 WinSendMsg (hwnd, WM_COMMAND,
  1415.                                     MPFROM2SHORT (DID_OK,0),
  1416.                                     0L);
  1417.                                 WinDismissDlg (hwnd, TRUE);
  1418.                                 return FALSE;
  1419.                             }
  1420.                             return FALSE;
  1421.                         case LN_SELECT:
  1422.                             if (Buffer [0] == '[')
  1423.                                 Buffer [0] = '\0';
  1424.                             WinSetWindowText (WinWindowFromID (hwnd,ID_OPENEDIT),
  1425.                                 Buffer);
  1426.                             return FALSE;
  1427.                         default:
  1428.                             return FALSE;
  1429.                         }
  1430.                     default:
  1431.                         return FALSE;
  1432.                 }
  1433.         case WM_INITDLG:
  1434.             WinSendDlgItemMsg (hwnd,ID_OPENEDIT,EM_SETTEXTLIMIT,
  1435.                 MPFROM2SHORT (PATHLENGTH, 0),
  1436.                 0);
  1437.             WinEnableWindow (WinWindowFromID (hwnd, DID_OK),
  1438.                 FALSE);
  1439.             InitDlg (hwnd);
  1440.             return FALSE;
  1441.         default:
  1442.             return WinDefDlgProc (hwnd, msg, mp1, mp2);
  1443.     }
  1444. }
  1445.  
  1446. VOID InitDlg (HWND hwnd)
  1447. {
  1448.     register int Drive;
  1449.     USHORT DriveNumber;
  1450.     ULONG LogicalDrives;
  1451.     char Buffer [PATHLENGTH];
  1452.     HDIR HSearch = 1;
  1453.     FILEFINDBUF FindBuf;
  1454.     USHORT FileCount = 1;
  1455.     char *PtrCh;
  1456.  
  1457.     GetPath (Buffer, sizeof (Buffer));
  1458.  
  1459.     WinSetWindowText (WinWindowFromID (hwnd, ID_OPENCD), Buffer);
  1460.     DosQCurDisk (&DriveNumber,&LogicalDrives);
  1461.     WinSendDlgItemMsg (hwnd, ID_OPENLIST,LM_DELETEALL, 0, 0);
  1462.     for (Drive = 'A'; Drive <= 'Z';++Drive)
  1463.     {
  1464.         if (LogicalDrives & 1)
  1465.         {
  1466.             sprintf (Buffer,"[-%c-]",Drive);
  1467.             WinSendDlgItemMsg (hwnd, ID_OPENLIST,
  1468.                 LM_INSERTITEM,MPFROM2SHORT (LIT_SORTASCENDING, 0),
  1469.                 MPFROMP (Buffer));
  1470.         }
  1471.         LogicalDrives >>= 1;
  1472.     }
  1473.     DosFindFirst ("*.*", &HSearch, 0x0010, &FindBuf, sizeof (FindBuf),
  1474.         &FileCount, 0L);
  1475.     while (FileCount)
  1476.     {
  1477.         if (FindBuf.attrFile & 0x0010 && !(FindBuf.achName [0] == '.' &&
  1478.             FindBuf.achName [1] == '\0'))
  1479.             {
  1480.                 sprintf (Buffer,"[%s]",FindBuf.achName);
  1481.                 WinSendDlgItemMsg (hwnd, ID_OPENLIST, LM_INSERTITEM,
  1482.                     MPFROM2SHORT (LIT_SORTASCENDING, 0), MPFROMP (Buffer));
  1483.             }
  1484.         else if (strcmp ((PtrCh = Extension (FindBuf.achName)),"TXT") == 0
  1485.             || strcmp (PtrCh,"C") == 0)
  1486.             WinSendDlgItemMsg (hwnd, ID_OPENLIST, LM_INSERTITEM,
  1487.                 MPFROM2SHORT (LIT_SORTASCENDING, 0),
  1488.                 MPFROMP (FindBuf.achName));
  1489.         DosFindNext (HSearch, &FindBuf,sizeof (FindBuf),&FileCount);
  1490.     }
  1491. }
  1492.  
  1493. MRESULT EXPENTRY SaveasProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  1494. {
  1495.     char FilePath [PATHLENGTH];
  1496.     char CurDir [PATHLENGTH + 22];
  1497.     char Buffer [2];
  1498.  
  1499.     switch (msg)
  1500.     {
  1501.         case WM_COMMAND:
  1502.             switch (COMMANDMSG(&msg)->cmd)
  1503.             {
  1504.                 case DID_OK:
  1505.                     WinQueryWindowText (WinWindowFromID (hwnd, ID_SAVEASEDIT),
  1506.                         sizeof (FilePath), FilePath);
  1507.                     if (FilePath [0])
  1508.                     {
  1509.                         if (SaveFile (FilePath) == FALSE)
  1510.                             WinMessageBox
  1511.                                 (HWND_DESKTOP, hwnd,
  1512.                                 "Error -- Cannot Save File",
  1513.                                 "PM Text Editor",
  1514.                                 0,
  1515.                                 MB_OK  |
  1516.                                 MB_ICONASTERISK);
  1517.                     else
  1518.                     {
  1519.                         Qualify (FilePath, FileName);
  1520.                         ShowFileName ();
  1521.                         Modified = 0;
  1522.                     }
  1523.                     WinDismissDlg (hwnd, TRUE);
  1524.                     return FALSE;
  1525.                     }
  1526.                     return FALSE;
  1527.                 case DID_CANCEL:
  1528.                     WinDismissDlg (hwnd, TRUE);
  1529.                     return FALSE;
  1530.                 default:
  1531.                     return FALSE;
  1532.             }
  1533.         case WM_CONTROL:
  1534.             switch (SHORT1FROMMP (mp1))
  1535.             {
  1536.                 case ID_SAVEASEDIT:
  1537.                     switch (SHORT2FROMMP (mp1))
  1538.                     {
  1539.                         case EN_CHANGE:
  1540.                             WinQueryWindowText ((HWND) mp2, 2, Buffer);
  1541.                             WinEnableWindow (WinWindowFromID (hwnd, DID_OK),
  1542.                                 Buffer [0]);
  1543.                             return FALSE;
  1544.                         default:
  1545.                             return FALSE;
  1546.                     }
  1547.                 default:
  1548.                     return FALSE;
  1549.             }
  1550.         case WM_INITDLG:
  1551.             WinSendDlgItemMsg( hwnd,ID_SAVEASEDIT,EM_SETTEXTLIMIT,
  1552.                 MPFROM2SHORT (PATHLENGTH,0),
  1553.                 0);
  1554.             WinEnableWindow (WinWindowFromID (hwnd, DID_OK), FALSE);
  1555.             GetPath (FilePath, sizeof (FilePath));
  1556.             sprintf (CurDir,"Current Directory: %s",FilePath);
  1557.             WinSetWindowText (WinWindowFromID (hwnd, ID_SAVEASCD), CurDir);
  1558.             return FALSE;
  1559.         default:
  1560.             return WinDefDlgProc (hwnd, msg, mp1, mp2);
  1561.     }
  1562. }
  1563.  
  1564. void NotYet (char *Message)
  1565. {
  1566.     char Buffer [60];
  1567.     sprintf (Buffer,"Not yet Implemented: %s",Message);
  1568.  
  1569.     WinMessageBox (HWND_DESKTOP, HFrame, Buffer,
  1570.         "PM Text Editor",
  1571.         0,
  1572.         MB_OK  |
  1573.         MB_ICONASTERISK);
  1574. }
  1575.  
  1576.  
  1577. #define MAXLINES 4096
  1578.  
  1579. static struct
  1580. {
  1581.     PCH LineAddress;
  1582.     unsigned char LineLength;
  1583. }
  1584. LineTable [MAXLINES];
  1585.  
  1586. static char LineBuffer [LINEBUFSIZ];
  1587. static unsigned LineSelector;
  1588. static unsigned LineOffset;
  1589. static SEL HeapSelector;
  1590.  
  1591. void BufInit (void)
  1592. {
  1593.     PCH FarPtr;
  1594.  
  1595.     FarPtr = (char far *)LineBuffer;
  1596.     LineSelector = SELECTOROF (FarPtr);
  1597.     LineOffset = OFFSETOF (FarPtr);
  1598. }
  1599.  
  1600. int DeleteChar (SHORT Line, SHORT Column)
  1601. {
  1602.     if (LineTable [Line].LineLength < 3 ||Column > 
  1603.             LineTable [Line].LineLength - 3)
  1604.         return FALSE;
  1605.     memmove (LineBuffer + Column, LineBuffer + Column + 1,
  1606.         LineTable [Line].LineLength - Column - 1);
  1607.     --LineTable [Line].LineLength;
  1608.     return TRUE;
  1609. }
  1610.  
  1611. void DeleteLine (SHORT Line)
  1612. {
  1613.     if (Line == LastLine)
  1614.     {
  1615.         LineBuffer [0] = '\n';
  1616.         LineBuffer [1] = '\0';
  1617.         LineTable [Line].LineLength = 2;
  1618.     }
  1619.     else
  1620.     {
  1621.         GetTempBuf (Line + 1);
  1622.         memmove (&LineTable [Line], &LineTable [Line + 1], (LastLine - Line)
  1623.             * sizeof (LineTable [0]));
  1624.         --LastLine;
  1625.     }
  1626. }
  1627.  
  1628. char *ErrorMessage (int ErrorNumber)
  1629. {
  1630.     static char *MessageTable [] = {
  1631.                                     "no error",
  1632.                                     "file open failure",
  1633.                                     "file too large",
  1634.                                     "maximum lines exceeded",
  1635.                                     "heap memory allocation failed",
  1636.                                     "unidentified error"
  1637.                                     };
  1638.  
  1639.     if (ErrorNumber >= sizeof (MessageTable) / sizeof (char *))
  1640.         ErrorNumber = sizeof (MessageTable) / sizeof (char *) - 1;
  1641.     return MessageTable [ErrorNumber];
  1642. }
  1643.  
  1644. PCH GetLineAddr (int Line)
  1645. {
  1646.     if (Line < 0 || Line > LastLine)
  1647.         return NULL;
  1648.     else
  1649.         return LineTable [Line].LineAddress;
  1650. }
  1651.  
  1652. SHORT GetLineLength (int Line)
  1653. {
  1654.     if (Line < 0 || Line > LastLine)
  1655.         return 0;
  1656.     else
  1657.         return LineTable [Line].LineLength - 2;
  1658. }
  1659.  
  1660. void GetTempBuf (int Line)
  1661. {
  1662.     movedata (SELECTOROF (LineTable[Line].LineAddress),
  1663.         OFFSETOF (LineTable[Line].LineAddress),
  1664.         LineSelector, LineOffset,
  1665.         LineTable [Line].LineLength);
  1666.     if (WinFreeMem (HHeap,
  1667.             (BYTE NEAR *)OFFSETOF (LineTable [Line].LineAddress),
  1668.             LineTable [Line].LineLength)
  1669.             != NULL)
  1670.             {
  1671.                 sprintf (Message,"managing heap; line %d",__LINE__);
  1672.                 ErrorQuit(Message);
  1673.             }
  1674.     LineTable [Line].LineAddress = MAKEP (LineSelector,LineOffset);
  1675. }
  1676.  
  1677. int InsertChar (SHORT Line, USHORT Character, SHORT Column, int Insert)
  1678. {
  1679.     unsigned char LineLength;
  1680.  
  1681.     LineLength = LineTable [Line].LineLength;
  1682.     if (Column > LINEBUFSIZ - 3 || LineLength >= LINEBUFSIZ && Insert)
  1683.         return FALSE;
  1684.     else if (Column == LineLength - 2)
  1685.     {
  1686.         LineBuffer [Column + 2] = LineBuffer [Column + 1];
  1687.         LineBuffer [Column + 1] = LineBuffer [Column];
  1688.  
  1689.         LineBuffer [Column] = (char)Character;
  1690.  
  1691.         ++LineTable [Line].LineLength;
  1692.         return TRUE;
  1693.     }
  1694.     else if (Column > LineLength - 2)
  1695.     {
  1696.         LineBuffer [Column + 2] = LineBuffer [LineLength - 1];
  1697.         LineBuffer [Column + 1] = LineBuffer [LineLength - 2];
  1698.         memset (LineBuffer + LineLength - 2,' ', Column - LineLength + 2);
  1699.         LineBuffer [Column] = (char)Character;
  1700.         LineTable [Line].LineLength = (unsigned char)Column + 3;
  1701.         return TRUE;
  1702.     }
  1703.     else
  1704.     {
  1705.         if (Insert)
  1706.         {
  1707.             memmove (LineBuffer + Column + 1,
  1708.                 LineBuffer + Column, LineLength - Column);
  1709.             ++LineTable [Line].LineLength;
  1710.     }
  1711.         LineBuffer [Column] = (char)Character;
  1712.         return TRUE;
  1713.     }
  1714. }
  1715.  
  1716. void InsertLine (SHORT Line, SHORT Column)
  1717. {
  1718.     NPCH HeapOffset;
  1719.     PCH HeapPointer;
  1720.  
  1721.     if (++LastLine >= MAXLINES)
  1722.     {
  1723.         sprintf (Message,"maximum lines reached; line %d",__LINE__);
  1724.         ErrorQuit (Message);
  1725.     }
  1726.     if (Column > LineTable [Line].LineLength - 2)
  1727.         Column = LineTable [Line].LineLength - 2;
  1728.     HeapOffset = WinAllocMem (HHeap, Column + 2);
  1729.     if (HeapOffset == NULL)
  1730.     {
  1731.         sprintf (Message,"out of heap memory; line %d",__LINE__);
  1732.         ErrorQuit (Message);
  1733.     }
  1734.  
  1735.     movedata (LineSelector, LineOffset, HeapSelector, (unsigned)HeapOffset,
  1736.                 Column);
  1737.     HeapPointer = MAKEP (HeapSelector, HeapOffset);
  1738.     *(HeapPointer + Column) = '\n';
  1739.     *(HeapPointer + Column + 1) = '\0';
  1740.     memmove (LineBuffer, LineBuffer + Column, LineTable [Line].LineLength
  1741.         - Column);
  1742.     LineTable [Line].LineLength -= (unsigned char)Column;
  1743.     memmove (&LineTable [Line + 1], &LineTable [Line],
  1744.         (LastLine - Line) * sizeof (LineTable [0]));
  1745.     LineTable [Line].LineAddress = HeapPointer;
  1746.     LineTable [Line].LineLength = (unsigned char)(Column + 2);
  1747. }
  1748.  
  1749. int JoinLine (SHORT Line)
  1750. {
  1751.     if (Line == 0)
  1752.         return FALSE;
  1753.     if (LineTable [Line].LineLength + LineTable [Line - 1].LineLength - 2 >
  1754.         LINEBUFSIZ)
  1755.         return FALSE;
  1756.     memmove (LineBuffer + LineTable [Line - 1].LineLength - 2, LineBuffer,
  1757.         LineTable [Line].LineLength);
  1758.     movedata (SELECTOROF (LineTable [Line - 1].LineAddress),
  1759.         OFFSETOF (LineTable [Line - 1].LineAddress),
  1760.         LineSelector, LineOffset, LineTable [Line - 1].LineLength - 2);
  1761.     LineTable [Line].LineLength += LineTable [Line - 1].LineLength - 2;
  1762.     if (WinFreeMem(HHeap, (BYTE NEAR *) OFFSETOF (LineTable [Line - 1].LineAddress),
  1763.         LineTable [Line - 1].LineLength) != NULL)
  1764.         {
  1765.             sprintf (Message,"managing heap; line %d",__LINE__);
  1766.             ErrorQuit (Message);
  1767.         }
  1768.     memmove (&LineTable [Line - 1], &LineTable [Line], (LastLine - Line + 1) *
  1769.         sizeof (LineTable [0]));
  1770.     --LastLine;
  1771.     return TRUE;
  1772. }
  1773.  
  1774. void NewFile (void)
  1775. {
  1776.     PCH FarPtr;
  1777.     LineBuffer [0] = '\n';
  1778.     LineBuffer [1] = '\0';
  1779.     LineTable [0].LineAddress = MAKEP (LineSelector, LineOffset);
  1780.     LineTable [0].LineLength = 2;
  1781.  
  1782.     LastLine = 0;
  1783.     HHeap = WinCreateHeap (0, 4096, 0, 0, 0, HM_MOVEABLE);
  1784.     FarPtr = WinLockHeap (HHeap);
  1785.     HeapSelector = SELECTOROF (FarPtr);
  1786. }
  1787.  
  1788. int ReadFile (char *FileName)
  1789. {
  1790.     FILE *PtrFile;
  1791.     long FileLength;
  1792.     USHORT HeapSize;
  1793.     NPCH HeapOffset;
  1794.     unsigned char LineLength;
  1795.     PCH FarPtr;
  1796.  
  1797.     if ((PtrFile = fopen (FileName,"r")) == NULL)
  1798.         return (ERROPEN);
  1799.     if ((FileLength = filelength (fileno (PtrFile))) == -1)
  1800.         return (ERROPEN);
  1801.     if (FileLength > 50000)
  1802.         return (ERRTOOBIG);
  1803.     HeapSize = (USHORT)(FileLength + FileLength / 5);
  1804.  
  1805.     HHeap = WinCreateHeap (0, HeapSize, 0, 0, 0, 0);
  1806.     FarPtr = WinLockHeap (HHeap);
  1807.     HeapSelector = SELECTOROF (FarPtr);
  1808.     LastLine = -1;
  1809.     while (fgets(LineBuffer,LINEBUFSIZ-1,PtrFile) != NULL)
  1810.     {
  1811.         if (++LastLine >= MAXLINES)
  1812.             return (ERRMAXLINES);
  1813.         LineLength = (unsigned char)strlen (LineBuffer) + 1;
  1814.  
  1815.         if (LineLength == LINEBUFSIZ - 1 && LineBuffer [LINEBUFSIZ - 3] 
  1816.                 != '\n')
  1817.         {
  1818.             LineBuffer [LINEBUFSIZ - 2] = '\n';
  1819.             LineBuffer [LINEBUFSIZ - 1] = '\0';
  1820.             ++LineLength;
  1821.         }
  1822.         HeapOffset = WinAllocMem (HHeap, LineLength);
  1823.         if (HeapOffset == NULL)
  1824.             return (ERRALLOC);
  1825.         movedata (LineSelector,LineOffset,HeapSelector,(unsigned)HeapOffset,
  1826.             LineLength);
  1827.         LineTable [LastLine].LineAddress = MAKEP (HeapSelector,HeapOffset);
  1828.         LineTable [LastLine].LineLength = LineLength;
  1829.     }
  1830.     GetTempBuf (0);
  1831.     fclose (PtrFile);
  1832.     return (0);
  1833. }
  1834.  
  1835. void ReleaseFile (void)
  1836. {
  1837.     if (HHeap != NULL)
  1838.         WinDestroyHeap (HHeap);
  1839.     return;
  1840. }
  1841.  
  1842. void ReleaseTempBuf (int Line)
  1843. {
  1844.     NPCH HeapOffset;
  1845.     HeapOffset = WinAllocMem (HHeap, LineTable [Line].LineLength);
  1846.     if (HeapOffset == NULL)
  1847.     {
  1848.         sprintf (Message,"Out of heap memory; line %d",__LINE__);
  1849.         ErrorQuit (Message);
  1850.     }
  1851.     movedata (LineSelector, LineOffset,HeapSelector,(unsigned)HeapOffset,
  1852.         LineTable [Line].LineLength);
  1853.     LineTable [Line].LineAddress = MAKEP (HeapSelector, HeapOffset);
  1854. }
  1855.  
  1856. int SaveFile (char *FileName)
  1857. {
  1858.     register int i;
  1859.     FILE *PtrFile;
  1860.     char TempBuffer [LINEBUFSIZ];
  1861.     PCH FarPtr;
  1862.     unsigned BufSel;
  1863.  
  1864.     if ((PtrFile = fopen (FileName,"w")) == NULL)
  1865.         return FALSE;
  1866.     FarPtr = (char far *)TempBuffer;
  1867.     BufSel = SELECTOROF (FarPtr);
  1868.     for (i = 0; i <= LastLine; ++i)
  1869.     {
  1870.         movedata (SELECTOROF (LineTable [i].LineAddress),
  1871.             OFFSETOF (LineTable [i].LineAddress), BufSel,
  1872.             (unsigned int) TempBuffer, LineTable [i].LineLength);
  1873.         fputs (TempBuffer, PtrFile);
  1874.     }
  1875.     fclose (PtrFile);
  1876.     return TRUE;
  1877. }
  1878.  
  1879. int SearchBuf (char *FindString, PSHORT Line, PSHORT Col)
  1880. {
  1881.     register int i, j;
  1882.     char far *FPtrCh;
  1883.  
  1884.     FPtrCh = LineTable [*Line].LineAddress + *Col;
  1885.     i = *Line;
  1886.     for (;;)
  1887.     {
  1888.         while (*FPtrCh)
  1889.         {
  1890.             for (j = 0; FindString [j] == FPtrCh [j] && FindString [j]; ++j)
  1891.                 ;
  1892.             if (FindString [j] == '\0')
  1893.             {
  1894.                 *Line = i;
  1895.                 *Col = FPtrCh + j - LineTable [i].LineAddress;
  1896.                 return TRUE;
  1897.             }
  1898.             ++FPtrCh;
  1899.         }
  1900.         if (++i > LastLine)
  1901.             return FALSE;
  1902.         FPtrCh = LineTable [i].LineAddress;
  1903.     }
  1904. }
  1905.  
  1906. void ErrorQuit (char *Message)
  1907. {
  1908.     char Buffer [60];
  1909.     sprintf (Buffer,"Program Error: %s",Message);
  1910.  
  1911.     WinMessageBox (HWND_DESKTOP,HFrame, Buffer, "PM Text Editor",
  1912.         0, MB_OK |
  1913.         MB_ICONHAND);
  1914.     Quit (1);
  1915. }
  1916.  
  1917. char *Extension (char *FileName)
  1918. {
  1919.     while (*FileName)
  1920.         if (*FileName++ == '.')
  1921.             return (FileName);
  1922.     return (FileName);
  1923. }
  1924.  
  1925. void GetPath (char *Path, unsigned PathSize)
  1926. {
  1927.     USHORT DriveNumber;
  1928.     ULONG LogicalDrives;
  1929.  
  1930.     if (PathSize < 3)
  1931.         return;
  1932.     DosQCurDisk (&DriveNumber, &LogicalDrives);
  1933.     sprintf (Path,"%c:\\",DriveNumber + 64);
  1934.     PathSize -= 3;
  1935.     DosQCurDir (DriveNumber, Path + 3, &(USHORT)PathSize);
  1936.     return;
  1937. }
  1938.  
  1939. void InitWindow (void)
  1940. {
  1941.     CursorCol = CursorLine = 0;
  1942.     TopLine = FirstCol = 0;
  1943.     TopLineMax = max (0,LastLine - yWin / yCharTot + 1);
  1944.     FirstColMax = LINEBUFSIZ - 2 - xWin / xChar;
  1945.     WinSendMsg (HVScroll, SBM_SETSCROLLBAR,
  1946.         MPFROM2SHORT (TopLine, 0),
  1947.         MPFROM2SHORT (0, TopLineMax));
  1948.     WinEnableWindow (HVScroll, TopLineMax ? TRUE : FALSE);
  1949.     WinSendMsg (HHScroll, SBM_SETSCROLLBAR,
  1950.     MPFROM2SHORT (FirstCol, 0),
  1951.     MPFROM2SHORT (0, FirstColMax));
  1952.     if (HClient == WinQueryFocus (HWND_DESKTOP,FALSE))
  1953.         WinCreateCursor (HClient, (CursorCol - FirstCol) * xChar,
  1954.             yWin - (CursorLine - TopLine + 1) * yCharTot, 0, 0,
  1955.             CURSOR_SETPOS,
  1956.             NULL);
  1957.     WinInvalidateRect (HClient, 0, FALSE);
  1958. }
  1959.  
  1960. void Qualify (char *Unqual, char *Qual)
  1961. {
  1962.     char PathBuffer [PATHLENGTH];
  1963.     char *PtrPath = PathBuffer;
  1964.     GetPath (PathBuffer, sizeof (PathBuffer));
  1965.  
  1966.     if (*(Unqual + 1) == ':')
  1967.     {
  1968.         *Qual++ = *Unqual++;
  1969.         *Qual++ = *Unqual++;
  1970.         PtrPath += 2;
  1971.     }
  1972.     else
  1973.     {
  1974.         *Qual++ = *PtrPath++;
  1975.         *Qual++ = *PtrPath++;
  1976.     }
  1977.     if (*Unqual != '\\')
  1978.     {
  1979.         while (*Qual++ = *PtrPath++)
  1980.                 ;
  1981.         if (*(Qual - 2) == '\\')
  1982.             --Qual;
  1983.         else
  1984.             *(Qual - 1) = '\\';
  1985.         }
  1986.     while (*Qual++ = *Unqual++)
  1987.         ;
  1988. }
  1989.  
  1990. void Quit (int ErrorCode)
  1991. {
  1992.     USHORT Reply;
  1993.     if (Modified)
  1994.     {
  1995.         Reply = WinMessageBox (HWND_DESKTOP, HClient,
  1996.             "File Unsaved; Save?",
  1997.             "PM Text Editor",
  1998.             0,
  1999.             MB_YESNO   |
  2000.             MB_ICONQUESTION);
  2001.         if (Reply == MBID_YES)
  2002.             while (Modified)
  2003.                 WinSendMsg (HClient, WM_COMMAND, MPFROM2SHORT (ID_SAVE, 0), 0L);
  2004.         }
  2005.         if (HHeap != NULL)
  2006.             WinDestroyHeap (HHeap);
  2007.         WinDestroyWindow (HFrame);
  2008.         WinDestroyMsgQueue (HMesQue);
  2009.         WinTerminate (HAncBlk);
  2010.         exit (ErrorCode);
  2011. }
  2012.  
  2013. void ShowFileName (void)
  2014. {
  2015.     sprintf (Title,"PM Editor - %s", FileName [0] ? Unqualify (FileName)
  2016.                                                   : "(Untitled)");
  2017.     WinSetWindowText (HFrame, Title);
  2018. }
  2019.  
  2020. char *Unqualify (char *Qual)
  2021. {
  2022.     char *PtrCh;
  2023.  
  2024.     PtrCh = Qual + strlen (Qual);
  2025.     while (PtrCh != Qual && *(PtrCh-1) != '\\' && *(PtrCh-1)  != ':')
  2026.         --PtrCh;
  2027.     WinUpper (HAncBlk, NULL, NULL, PtrCh);
  2028.     return (PtrCh);
  2029. }
  2030.  
  2031.  
  2032.  
  2033.  
  2034.  
  2035.  
  2036.  
  2037.  
  2038.  
  2039.