home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Pascal / Applications / ircle 1.5.1 / source / ircle sources / InputLine.p < prev    next >
Encoding:
Text File  |  1993-11-24  |  8.4 KB  |  412 lines  |  [TEXT/PJMM]

  1. {    ircle - Internet Relay Chat client    }
  2. {    File: InputLine    }
  3. {    Copyright © 1992 Olaf Titz (s_titz@ira.uka.de)    }
  4.  
  5. {    This program is free software; you can redistribute it and/or modify    }
  6. {    it under the terms of the GNU General Public License as published by    }
  7. {    the Free Software Foundation; either version 2 of the License, or    }
  8. {    (at your option) any later version.    }
  9.  
  10. {    This program is distributed in the hope that it will be useful,    }
  11. {    but WITHOUT ANY WARRANTY; without even the implied warranty of    }
  12. {    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    }
  13. {    GNU General Public License for more details.    }
  14.  
  15. {    You should have received a copy of the GNU General Public License    }
  16. {    along with this program; if not, write to the Free Software    }
  17. {    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.    }
  18.  
  19. unit InputLine;
  20. { Provides a small window with status and input lines. }
  21. { All keystrokes go into the input line. Implements a command history.}
  22.  
  23. interface
  24. uses
  25.     MiscGlue, ApplBase, MsgWindows;
  26.  
  27. procedure InitInputLine;
  28. { Startup }
  29.  
  30. procedure OpenInputLine (process: ProcPtr);
  31. { Open the input line window }
  32. { process(var s:string) gets called whenever Return was pressed }
  33.  
  34. procedure SetInputLine (var s: string);
  35. { Preset the input line }
  36.  
  37. procedure InsertInputLine (var s: string; select: boolean);
  38. { Insert a string into the input line }
  39.  
  40. procedure StatusLine (var s: string);
  41. { Set the status line }
  42.  
  43. procedure CloseInputLine;
  44. { Close the window }
  45.  
  46. implementation
  47.  
  48. const
  49.     MAXHIST = 5000;    { Maximum # of chars to store in command history }
  50.     MAXLINE = 240;        { Maximum length of input line }
  51.  
  52. var
  53.     iw: WindowPtr;
  54.     Hact, Hupd, Hmouse, Hkey, Hakey, Hidle, Hpaste: integer;
  55.     status: string[80];
  56.     lineh: TEHandle;
  57.     procs: ProcPtr;
  58.     line1, line2, letterw: integer;
  59.     ReturnHit: boolean;
  60.     hist: CharsHandle;
  61.     hpos: integer;
  62.  
  63. procedure initInputLine;
  64.     var
  65.         i: integer;
  66.     begin
  67.         iw := nil;
  68.         lineh := nil;
  69.         hist := CharsHandle(NewHandle(1));
  70.         hist^^[0] := chr(0);
  71.         hpos := 0;
  72.     end;
  73.  
  74. procedure DoRedraw (l: integer);
  75.     var
  76.         p0: GrafPtr;
  77.     begin
  78.         GetPort(p0);
  79.         SetPort(iw);
  80.         if l = 1 then begin
  81.             MoveTo(1, line1);
  82.             DrawString(status);
  83.         end
  84.         else begin
  85.             TEUpdate(lineh^^.viewRect, lineh);
  86.         end;
  87.         SetPort(p0);
  88.     end;
  89.  
  90. procedure StackupLine (var line: string);
  91.     var
  92.         i: integer;
  93.     begin
  94.         if gethandlesize(Handle(hist)) > MAXHIST then begin
  95.             i := 1;
  96.             while hist^^[i] <> chr(0) do
  97.                 i := succ(i);
  98.             i := Munger(Handle(hist), 0, nil, i, ptr(1), 0);
  99.         end;
  100.         i := length(line) + 1;
  101.         if i > 1 then begin
  102.             line[i] := chr(0);
  103.             i := PtrAndHand(@line[1], Handle(hist), i);
  104.             hpos := gethandlesize(Handle(hist)) - 1;
  105.         end
  106.     end;
  107.  
  108. procedure RecallLine (p: integer);
  109.     var
  110.         i: integer;
  111.         s: string;
  112.     begin
  113.         hpos := p;
  114.         i := 0;
  115.         repeat
  116.             p := succ(p);
  117.             i := succ(i);
  118.             s[i] := hist^^[p];
  119.         until s[i] = chr(0);
  120.         s[0] := chr(i - 1);
  121.         SetInputLine(s);
  122.     end;
  123.  
  124. procedure RecallLineUp;
  125.     var
  126.         i: integer;
  127.     begin
  128.         i := hpos;
  129.         if i > 0 then
  130.             repeat
  131.                 i := pred(i)
  132.             until hist^^[i] = chr(0);
  133.         RecallLine(i);
  134.     end;
  135.  
  136. procedure RecallLineDown;
  137.     var
  138.         i: integer;
  139.     begin
  140.         i := hpos;
  141.         if i < gethandlesize(handle(hist)) - 1 then begin
  142.             repeat
  143.                 i := succ(i)
  144.             until hist^^[i] = chr(0);
  145.             if i < gethandlesize(handle(hist)) - 1 then
  146.                 RecallLine(i)
  147.         end
  148.     end;
  149.  
  150.  
  151. procedure SetCursor (n: integer);
  152.     begin
  153.         if n < 1 then
  154.             n := 1
  155.         else if n > MAXLINE then
  156.             n := MAXLINE;
  157.         TESetSelect(n, n, lineh);
  158.         DoRedraw(2);
  159.     end;
  160.  
  161.  
  162. function Activate (var e: EventRecord): boolean;
  163.     begin
  164.         if iw <> nil then
  165.             if bitand(e.message, 1) = 1 then begin
  166.                 ShowWindow(iw);
  167.                 TEActivate(lineh)
  168.             end
  169.             else begin
  170.                 TEDeActivate(lineh);
  171.                 HideWindow(iw);
  172.             end;
  173.         Activate := false
  174.     end;
  175.  
  176. function Update (var e: EventRecord): boolean;
  177.     begin
  178.         if WindowPtr(e.message) = iw then begin
  179.             BeginUpdate(iw);
  180.             MoveTo(1, line1);
  181.             DrawString(status);
  182.             TEUpdate(lineh^^.viewRect, lineh);
  183.             EndUpdate(iw);
  184.             Update := true
  185.         end
  186.         else
  187.             Update := false
  188.     end;
  189.  
  190. function Mouse (var e: EventRecord): boolean;
  191.     begin
  192.         if WindowPtr(e.message) = iw then begin
  193.             GlobalToLocal(e.where);
  194.             if e.where.v < 11 then begin
  195.                 e.what := mouseMsg + inDrag;
  196.                 LocalToGlobal(e.where);
  197.                 ApplEvents(e);  { Let ApplBase do the dragging }
  198.             end
  199.             else begin
  200.                 TEClick(e.where, false, lineh);
  201.             end;
  202.             Mouse := true
  203.         end
  204.         else
  205.             Mouse := false;
  206.     end;
  207.  
  208. procedure SCALL (var s: string; p: ProcPtr);
  209. inline
  210.     $205F, $4E90;        { movea.l (a7)+,a0; jsr (a0) }
  211.  
  212. procedure GotLine;
  213.     var
  214.         i: integer;
  215.         c: string[1];
  216.         line: string;
  217.     begin
  218.         ReturnHit := true;
  219.         i := lineh^^.teLength;
  220.         if i > 255 then
  221.             i := 255;
  222.         BlockMove(lineh^^.htext^, @line[1], i);
  223.         while (i > 0) and (line[i] = ' ') do
  224.             i := pred(i);
  225.         line[0] := chr(i);
  226.         StackupLine(line);
  227.         c := '';
  228.         SetInputLine(c);
  229.         SCALL(line, procs);
  230.         ReturnHit := false;
  231.     end;
  232.  
  233.  
  234. function Key (var e: EventRecord): boolean;
  235.     var
  236.         c: char;
  237.         i: integer;
  238.         p0: GrafPtr;
  239.     begin
  240.         if iw = nil then
  241.             Key := false
  242.         else if not ReturnHit then begin
  243.             getPort(p0);
  244.             SetPort(iw);
  245.             c := chr(e.message mod 256);
  246.             case ord(c) of
  247.                 13: 
  248.                     GotLine;
  249.                 21:  { ^U }
  250.                     begin
  251.                     TEKey(chr(C_UNDERLINE), lineh);
  252.                     TESelView(lineh)
  253.                 end;
  254.                 30: 
  255.                     RecallLineUp;
  256.                 31: 
  257.                     RecallLineDown;
  258.                 otherwise
  259.                     begin
  260.                     TEKey(c, lineh);
  261.                     TESelView(lineh)
  262.                 end;
  263.             end;
  264.             SetPort(p0);
  265.         end;
  266.         Key := true;
  267.     end;
  268.  
  269. function AKey (var e: EventRecord): boolean;
  270.     begin
  271.         AKey := Key(e)
  272.     end;
  273.  
  274. function Idle (var e: EventRecord): boolean;
  275.     begin
  276.         TEIdle(lineh);
  277.         Idle := false;
  278.     end;
  279.  
  280. function Paste (var e: EventRecord): boolean;
  281.     var
  282.         h: CharsHandle;
  283.         i, n, c: integer;
  284.         f: EventRecord;
  285.         b: boolean;
  286.     begin
  287.         if e.message = 5 then begin
  288.             i := TEFromScrap;
  289.             h := CharsHandle(TEScrapHandle);
  290.             n := TEGetScrapLen;
  291.             for i := 0 to n - 1 do begin
  292.                 c := ord(h^^[i]);
  293.                 f.message := c;
  294.                 b := Key(f);
  295.                 if c = 13 then
  296.                     repeat
  297.                         ApplRun
  298.                     until not ReturnHit;
  299.             end;
  300.             Paste := true
  301.         end
  302.         else
  303.             Paste := false
  304.     end;
  305.  
  306. procedure OpenInputLine (process: ProcPtr);
  307.     var
  308.         p0: GrafPtr;
  309.         fi: FontInfo;
  310.         r: Rect;
  311.         i: integer;
  312.     begin
  313.         if iw = nil then begin
  314.             for i := 1 to 80 do begin
  315.                 Status[i] := ' ';
  316.             end;
  317.             ReturnHit := false;
  318.             Status[0] := chr(80);
  319.             SetRect(r, 0, 0, 16, 16);
  320.             iw := NewWindow(nil, r, '', false, 3, WindowPtr(-1), false, 0);
  321.             if iw <> nil then begin
  322.                 GetPort(p0);
  323.                 SetPort(iw);
  324.                 SetOrigin(-2, -2);
  325.                 penMode(patXor);
  326.                 TextFont(monaco);
  327.                 TextSize(9);
  328.                 TextFace([]);
  329.                 TextMode(srcCopy);
  330.                 GetFontInfo(fi);
  331.                 line1 := fi.ascent + fi.leading;
  332.                 line2 := line1 + fi.descent + fi.leading + fi.ascent + 1;
  333.                 letterw := fi.widMax;
  334.                 SizeWindow(iw, 80 * letterw + 4, line2 + fi.descent + fi.leading + 6, true);
  335.                 with screenBits.bounds do
  336.                     MoveWindow(iw, (right - left - iw^.portRect.right + 2) div 2 - 1, bottom - iw^.portRect.bottom - 5, true);
  337.                 SetRect(r, 0, line1 + fi.descent + 1, 80 * letterw, line2 + fi.descent);
  338.                 lineh := TENew(r, r);
  339.                 if lineh <> nil then begin
  340.                     Hact := ApplTask(@Activate, app4Evt);
  341.                     Hupd := ApplTask(@Update, updateEvt);
  342.                     Hmouse := ApplTask(@Mouse, mouseMsg + inContent);
  343.                     Hkey := ApplTask(@Key, keyDown);
  344.                     Hakey := ApplTask(@Akey, autoKey);
  345.                     Hidle := ApplTask(@Idle, nullEvent);
  346.                     Hpaste := ApplTask(@Paste, menuMsg + editMenu);
  347.                     SetPort(p0);
  348.                     ShowWindow(iw);
  349.                     TEAutoView(true, lineh);
  350.                     TEActivate(lineh);
  351.                     procs := process;
  352.                 end;
  353.             end
  354.         end;
  355.     end;
  356.  
  357. procedure StatusLine (var s: string);
  358.     begin
  359.         status := s;
  360.         DoRedraw(1);
  361.     end;
  362.  
  363.  
  364. procedure InsertInputLine (var s: string; select: boolean);
  365.     var
  366.         i, k: integer;
  367.         f: EventRecord;
  368.         b: boolean;
  369.     begin
  370.         repeat
  371.             i := pos(chr(13), s);
  372.             if i = 0 then begin
  373.                 k := lineh^^.selStart;
  374.                 TEInsert(@s[1], length(s), lineh);
  375.                 if select then
  376.                     TESetSelect(k, k + length(s), lineh);
  377.                 TESelView(lineh);
  378.                 exit(InsertInputLine);
  379.             end;
  380.             TEInsert(@s[1], i - 1, lineh);
  381.             GotLine; { this might cause reentrance! }
  382.             delete(s, 1, i);
  383.         until s = '';
  384.     end;
  385.  
  386. procedure SetInputLine (var s: string);
  387.     begin
  388.         if iw <> nil then begin
  389.             TEDeactivate(lineh);
  390.             TESetSelect(0, 32767, lineh);
  391.             TEDelete(lineh);
  392.             InsertInputLine(s, false);
  393.             SetCursor(length(s) + 1);
  394.             TESelView(lineh);
  395.             TEActivate(lineh);
  396.         end
  397.     end;
  398.  
  399. procedure CloseInputLine;
  400.     begin
  401.         ApplUntask(Hact);
  402.         ApplUntask(Hupd);
  403.         ApplUntask(Hmouse);
  404.         ApplUntask(Hkey);
  405.         ApplUntask(Hakey);
  406.         ApplUntask(Hidle);
  407.         ApplUntask(Hpaste);
  408.         DisposeWindow(iw);
  409.         iw := nil
  410.     end;
  411.  
  412. end.