home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1991 / 05 / trickbox / trickbox.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1991-04-03  |  16.7 KB  |  509 lines

  1. PROGRAM TrickBox;
  2. (* (c) 1991 Ralf Hensmann & toolbox *)
  3.  
  4. (************************************************************************)
  5. (*                                                                      *)
  6. (*                             Import                                   *)
  7. (*                                                                      *)
  8. (* ScreenLow:   SaveGroundLine         - speichert die unterste Zeile   *)
  9. (*              RestoreGroundLine      - restort die unterste Zeile     *)
  10. (*                                                                      *)
  11. (* Interpreter: PStatus                - Z. auf Bildschirminh. & Status *)
  12. (*              InitScreen             - Initialisiert Schirm           *)
  13. (*              SaveState(b) : PStatus - speichert Status in Zeiger     *)
  14. (*              RestoreState(PStatus,b)- baut Schirm nach Zeiger auf    *)
  15. (*              PrintCode(CHAR,BOOLEAN)- schreibt Code auf Schirm       *)
  16. (*                                       wenn die Boolean-Variable TRUE *)
  17. (*                                       ist, wird die Zeitverzögerung  *)
  18. (*                                       verwendet.                     *)
  19. (*              PrintChar(CHAR,BOOLEAN)- schreibt Zeichen auf Schirm    *)
  20. (*                                       BOOLEAN wie bei Printchar      *)
  21. (*              PrintState             - BOOLEAN-Variable, die angibt,  *)
  22. (*                                       ob die Operation erfolgreich   *)
  23. (*                                       war (TRUE) oder nicht.         *)
  24. (*              WriteStatusLine(i)     - Gibt die Statuszeile aus       *)
  25. (*                                                                      *)
  26. (************************************************************************)
  27. USES  Dos, Interpreter, ScreenLow, Crt;
  28.  
  29.  
  30. CONST CMax      = 15000;
  31.       CtrlChar  = #254;
  32.  
  33. VAR   CharBuf     : ARRAY [0..CMax] OF CHAR;
  34.       CharLast    : WORD;
  35.       CtrlMode    : BOOLEAN;
  36.       LastX,LastY : BYTE;
  37.       ProgPath    : STRING;
  38.  
  39. (************************************************************************)
  40. (*                                                                      *)
  41. (*                         Stackoperationen                             *)
  42. (*                                                                      *)
  43. (* Push, Pop, Top und Clear sind Stackoperationen für den Screen-Stack, *)
  44. (* der für die Undo-Funktion zum schnelleren Bildaufbau verwendet wird. *)
  45. (*                                                                      *)
  46. (************************************************************************)
  47. CONST MaxStack   = 9;
  48. VAR   Stack      : ARRAY [0..MaxStack] OF PStatus;
  49.       StackPtr   : WORD;
  50.  
  51. PROCEDURE InitStack;
  52. BEGIN
  53.   FOR StackPtr := MaxStack DOWNTO 0 DO
  54.     Stack[StackPtr] := NIL;
  55. END;
  56.  
  57. FUNCTION Pop : PStatus;
  58. BEGIN
  59.   IF StackPtr = 0 THEN
  60.     Pop := NIL
  61.   ELSE BEGIN
  62.     Dec(StackPtr);
  63.     Pop := Stack[StackPtr];
  64.   END;
  65. END;
  66.  
  67. PROCEDURE Push(P : PStatus);
  68. BEGIN
  69.   IF StackPtr = MaxStack+1 THEN BEGIN
  70.     Dispose(Stack[0]);
  71.     Move(Stack[1],Stack[0],MaxStack*SizeOf(PStatus));
  72.     Stack[MaxStack] := P;
  73.   END ELSE BEGIN
  74.     Stack[StackPtr] := P;
  75.     Inc(StackPtr);
  76.   END;
  77. END;
  78.  
  79. FUNCTION Top : PStatus;
  80. BEGIN
  81.   IF StackPtr = 0 THEN Top := NIL
  82.                   ELSE Top := Stack[StackPtr-1];
  83. END;
  84.  
  85. PROCEDURE Clear;
  86. BEGIN
  87.   WHILE StackPtr > 0 DO BEGIN
  88.     Dec(StackPtr);
  89.     Dispose(Stack[StackPtr]);
  90.   END;
  91. END;
  92. (************************************************************************)
  93. (*                    Ende der Stackoperationen                         *)
  94. (************************************************************************)
  95.  
  96. (************************************************************************)
  97. (*                                                                      *)
  98. (*                           Hilfsroutinen                              *)
  99. (*                                                                      *)
  100. (************************************************************************)
  101.  
  102. (************************************************************************)
  103. (* GetKey liest von der Tastatur eine erweiterte Taste ein. Speziellen  *)
  104. (* Tasten wird 1000 zum Wert dazuaddiert.                               *)
  105. FUNCTION GetKey : INTEGER;
  106. VAR CH : CHAR;
  107. BEGIN
  108.   CH:= ReadKey;
  109.   IF CH = #0 THEN GetKey := 1000+Ord(ReadKey)
  110.              ELSE GetKey := Ord(CH);
  111. END;
  112.  
  113. (************************************************************************)
  114. (* Wait wartet auf einen Tastendruck. Vorher getippte Tasten werden     *)
  115. (* überlesen.                                                           *)
  116. PROCEDURE Wait;
  117. VAR Dummy : INTEGER;
  118. BEGIN
  119.   WHILE KeyPressed DO Dummy := GetKey;
  120.   Dummy := GetKey;
  121. END;
  122.  
  123. (************************************************************************)
  124. (* ClearSession löscht die gesamte bisherige Aktion                     *)
  125. PROCEDURE ClearSession;
  126. BEGIN
  127.   CharLast := 0;
  128.   CtrlMode := FALSE;
  129.   Clear;
  130.   InitScreen;
  131. END;
  132.  
  133. (************************************************************************)
  134. (* LowPlaySession spielt eine Sequenz von einer Position im Buffer bis  *)
  135. (* zu einer neuen Position im Puffer ab. Die Variable CtrlMode gibt an, *)
  136. (* ob sich die Wiedergabe gerade im Kontrollmodus aufhält.              *)
  137. PROCEDURE LowPlaySession( FromP,Top : WORD);
  138. VAR i : WORD;
  139. BEGIN
  140.   i := FromP;
  141.   WHILE i < Top DO BEGIN
  142.     IF CharBuf[i] = CtrlChar THEN
  143.       CtrlMode := NOT CtrlMode
  144.     ELSE
  145.       IF CtrlMode THEN PrintCode(CharBuf[i],FALSE)
  146.                   ELSE PrintChar(CharBuf[i],FALSE);
  147.     (* Screens abspeichern *)
  148.     IF i MOD 5 = 4 THEN
  149.       Push(SaveState(CtrlMode));
  150.     Inc(i);
  151.   END;
  152. END;
  153.  
  154. (************************************************************************)
  155. (* PlaySession spielt die Session ab, wie dies auch normal geschehen    *)
  156. (* würde. Zeitverzögerungen werden hier berücksichtigt. Jeder Tasten-   *)
  157. (* druck hält die Session an, ESCAPE bricht die Session ab und löscht   *)
  158. (* den Rest der Session.                                                *)
  159. PROCEDURE PlaySession;
  160. VAR i        : WORD;
  161.     Key      : INTEGER;
  162. BEGIN
  163.   i := 0;
  164.   CtrlMode := FALSE;
  165.   InitScreen;
  166.   WHILE i < CharLast DO BEGIN
  167.     IF CharBuf[i] = CtrlChar THEN
  168.       CtrlMode := NOT CtrlMode
  169.     ELSE
  170.       IF CtrlMode THEN PrintCode(CharBuf[i],TRUE)
  171.                   ELSE PrintChar(CharBuf[i],TRUE);
  172.     (* Screens abspeichern *)
  173.     IF i MOD 5 = 4 THEN
  174.       Push(SaveState(CtrlMode));
  175.     IF KeyPressed THEN BEGIN
  176.       Key := GetKey;
  177.       IF Key = 27 THEN BEGIN
  178.         CharLast := i+1; Exit;
  179.       END;
  180.       Exit;
  181.     END;
  182.     Inc(i);
  183.   END;
  184. END;
  185.  
  186. (************************************************************************)
  187. (* Undo-Session nimmt einen Zug zurück. Undo-Session verwendet den      *)
  188. (* letzten, auf dem Stack gespeicherten Zug.                            *)
  189. PROCEDURE UndoSession;
  190. VAR LastScreen : PStatus;
  191.     i,Back     : WORD;
  192. BEGIN
  193.   REPEAT
  194.     IF CharLast = 0 THEN Exit;
  195.     LastScreen := Top;
  196.     IF LastScreen = NIL THEN BEGIN
  197.       CtrlMode := FALSE;
  198.       InitScreen;
  199.       LowPlaySession(0,CharLast-1);
  200.     END ELSE BEGIN
  201.       i := 5*(CharLast DIV 5);
  202.       IF i = CharLast THEN BEGIN
  203.         LastScreen := Pop; Dispose(LastScreen);
  204.         LastScreen := Top;
  205.         Dec(i,5);
  206.       END;
  207.       IF LastScreen <> NIL THEN BEGIN
  208.         RestoreState(LastScreen,CtrlMode);
  209.         LowPlaySession(i,CharLast-1);
  210.       END ELSE BEGIN
  211.         CtrlMode := FALSE;
  212.         InitScreen;
  213.         LowPlaySession(0,CharLast-1);
  214.       END;
  215.     END;
  216.     Dec(CharLast);
  217.   UNTIL (CharLast=0) OR (CharBuf[CharLast-1] <> CtrlChar);
  218. END;
  219.  
  220. (************************************************************************)
  221. (* SaveSession speichert eine Session als Textfile ab. Die Zeilenlänge  *)
  222. (* ist 75 Zeichen, damit mit einem Texteditor editiert werden kann.     *)
  223. FUNCTION SaveSession( Name : STRING) : BOOLEAN;
  224. VAR t        : TEXT;
  225.     i,ccount : WORD;
  226.     st       : STRING[80];
  227. BEGIN
  228.   IF Name = '' THEN BEGIN
  229.     SaveSession := FALSE;
  230.     Exit;
  231.   END;
  232.   SaveSession := IOResult = 0;
  233.   (*$I-*)
  234.   Assign(t,Name); ReWrite(t);
  235.   i := 0; ccount := CharLast;
  236.   st[0] := CHAR(75);
  237.   WHILE ccount > 75 DO BEGIN
  238.     Move(CharBuf[i],st[1],75);
  239.     WriteLn(t,st);
  240.     Dec(ccount,75);
  241.     Inc(i,75);
  242.   END;
  243.   st[0] := CHAR(ccount);
  244.   Move(CharBuf[i],st[1],ccount);
  245.   WriteLn(t,st);
  246.   Close(t);
  247.   (*$I+*)
  248.   SaveSession := IOResult = 0;
  249. END;
  250.  
  251. (************************************************************************)
  252. (* Error gibt eine Fehlermeldung aus und wartet auf einen Tastendruck   *)
  253. PROCEDURE Error(Meldung : STRING);
  254. VAR H : PStatus;
  255. BEGIN
  256.   H := SaveState(CtrlMode);
  257.   ClrScr;
  258.   GotoXY(10,10);
  259.   Write(Meldung);
  260.   Wait;
  261.   RestoreState(H,CtrlMode);
  262.   Dispose(H);
  263. END;
  264.  
  265. (************************************************************************)
  266. (* LoadSession lädt eine Session von der Platte. Die Session sofort     *)
  267. (* ausgeführt.                                                          *)
  268. FUNCTION LoadSession(Name : STRING) : BOOLEAN;
  269. VAR t     : TEXT;
  270.     Zeile : STRING;
  271.     i     : INTEGER;
  272. BEGIN
  273.   IF Name = '' THEN BEGIN
  274.     LoadSession := FALSE;
  275.     Exit;
  276.   END;
  277.   (* Session in Puffer laden *)
  278.   Assign(t,Name);
  279.   {$I-} Reset(t); {$I+}
  280.   IF IOResult <> 0 THEN BEGIN
  281.     Error('Datei ist nicht auffindbar');
  282.     LoadSession := FALSE;
  283.     Exit;
  284.   END;
  285.   ClearSession;
  286.   i := 0;
  287.   REPEAT
  288.     ReadLn(t,Zeile);
  289.     Move(Zeile[1],CharBuf[i],Length(Zeile));
  290.     Inc(i,Length(Zeile));
  291.   UNTIL EoF(t);
  292.   CharLast := i;
  293.   CtrlMode := FALSE;
  294.   InitScreen;
  295.   LowPlaySession(0,CharLast);
  296.   LoadSession := TRUE;
  297. END;
  298.  
  299. (************************************************************************)
  300. (*                       Ende der Hilfsroutinen                         *)
  301. (************************************************************************)
  302.  
  303. PROCEDURE Help;
  304. VAR H : PStatus;
  305.     t : TEXT;
  306.     i : INTEGER;
  307.     Zeile : STRING;
  308. BEGIN
  309.   H := SaveState(CtrlMode);
  310.   TextColor(LightGray); TextBackground(Black);
  311.   Assign(t,ProgPath+'TRICKBOX.HLP');
  312.   (*$I-*) Reset(t); (*$I+*)
  313.   IF IOResult <> 0 THEN BEGIN
  314.     ClrScr;
  315.     GotoXY(10,10);
  316.     WriteLn('Hilfsdatei nicht gefunden...');
  317.   END ELSE BEGIN
  318.     ClrScr;
  319.     FOR i := 1 TO 25 DO BEGIN
  320.       ReadLn(t,Zeile);
  321.       GotoXY(1,i);
  322.       Write(Zeile);
  323.     END;
  324.     Close(t);
  325.   END;
  326.   Wait;
  327.   RestoreState(H,CtrlMode);
  328.   Dispose(H);
  329. END;
  330.  
  331. (************************************************************************)
  332. (* EditSession editiert die Session, d.h. hängt neue Events an die bis- *)
  333. (* herige Session an. EditSession macht die unterste Zeile zur Status-  *)
  334. (* zeile, die automatisch verschwindet, sobald der Cursor auf der Zeile *)
  335. (* steht. EditSession selbst verwaltet nur "Meta-Events", wie das       *)
  336. (* Zurücknehmen eines Events. Alle anderen Events werden von EditSes-   *)
  337. (* sion nur abgespeichert, wie z.B. Farben einstellen bzw. in spezielle *)
  338. (* Kommandos umgewandelt wie INS/OVR.                                   *)
  339. PROCEDURE EditSession;
  340.   PROCEDURE Send(CH : CHAR; M : BOOLEAN);
  341.   BEGIN
  342.     IF M <> CtrlMode THEN BEGIN
  343.       CharBuf[CharLast] := CtrlChar;
  344.       Inc(CharLast);
  345.       LowPlaySession(CharLast-1,CharLast);
  346.     END;
  347.     CharBuf[CharLast] := CH;
  348.     Inc(CharLast);
  349.     LowPlaySession(CharLast-1,CharLast);
  350.   END;
  351. VAR Key,CX,cy,CKey : INTEGER;
  352.     CCh            : CHAR;
  353.     Tb             : BYTE;
  354. BEGIN
  355.   REPEAT
  356.     IF WhereY <> 25 THEN BEGIN
  357.       SaveGroundLine;
  358.       CX := WhereX; cy := WhereY;
  359.       WriteStatusLine(CharLast);
  360.       GotoXY(CX,cy);
  361.       Key := GetKey;
  362.       RestoreGroundLine;
  363.     END ELSE
  364.       Key := GetKey;
  365.     CASE Key OF
  366.       32..126,
  367.       128..254: Send(Chr(Key),FALSE);
  368.       1059    : Help;                   (* Hilfestellung *)
  369.       1072    : Send('^',TRUE);         (* Pfeiltasten *)
  370.       1075    : Send('<',TRUE);
  371.       1077    : Send('>',TRUE);
  372.       1080    : Send('_',TRUE);
  373.       1071    : Send('{',TRUE);         (* Home,End *)
  374.       1079    : Send('}',TRUE);
  375.       1073    : Send('(',TRUE);         (* PgUp, PgDown *)
  376.       1081    : Send(')',TRUE);
  377.       1083    : Send('$',TRUE);         (* DEL, BS *)
  378.          8    : Send('&',TRUE);
  379.       1115    : Send('[',TRUE);         (* Ctrl-Pfeiltasten *)
  380.       1116    : Send(']',TRUE);
  381.         13    : Send('R',TRUE);         (* RETURN *)
  382.         26    : Send('Z',TRUE);         (* ^Z für ClrScr *)
  383.       1082    : Send('#',TRUE);         (* INS *)
  384.         23    : Send('W',TRUE);         (* ^W für Warten *)
  385.         14    : Send('X',TRUE);         (* ^N für Zeile einfügen *)
  386.         25    : Send('Y',TRUE);         (* ^Y für Zeile löschen *)
  387.       1035    : Send('!',TRUE);         (* Alt-H für hellen Hintergrund *)
  388.       1038    : Send('?',TRUE);         (* Alt-L für Line-Modus *)
  389.       1031    : Send('-',TRUE);         (* Alt-S für Single-Line Modus *)
  390.       1032    : Send('=',TRUE);         (* Alt-D für Double-Line Modus *)
  391.       1046    : Send('+',TRUE);         (* Alt-C für Zeilen doppeln *)
  392.       1120    : Send('*',TRUE);         (* Alt-1 für schneller *)
  393.       1121    : Send('~',TRUE);         (* Alt-2 für langsamer *)
  394.       1049    : Send('/',TRUE);         (* Alt-N für Zeilen-Modus aus *)
  395.       1022    : Send('U',TRUE);         (* Alt-U für Rubber-Mode *)
  396.        127    : UndoSession;            (* Ctrl-Backspace für Undo *)
  397.         11    : BEGIN                   (* Ctrl-K für Vordergrundfarbe *)
  398.                   SaveGroundLine;
  399.                   GotoXY(1,25);
  400.                   Write('Vordergrund (A..P) : ');
  401.                   CKey := GetKey;
  402.                   RestoreGroundLine;
  403.                   IF (CKey <=256) THEN BEGIN
  404.                     CCh := UpCase(Chr(CKey));
  405.                     IF (CCh>='A') AND (CCh<='P') THEN
  406.                       Send(CCh,TRUE);
  407.                   END;
  408.                 END;
  409.         17    : BEGIN                   (* Ctrl-K für Vordergrundfarbe *)
  410.                   SaveGroundLine;
  411.                   GotoXY(1,25);
  412.                   Write('Hintergrund (A..P) : ');
  413.                   CKey := GetKey;
  414.                   RestoreGroundLine;
  415.                   IF (CKey <=256) THEN BEGIN
  416.                     CCh := UpCase(Chr(CKey));
  417.                     IF (CCh>='A') AND (CCh<='P') THEN
  418.                       Send(Chr(Ord(CCh)+32),TRUE);
  419.                   END;
  420.                 END;
  421.     END;
  422.   UNTIL Key = 27;
  423.   TextColor(LightGray);
  424.   TextBackground(Black);
  425. END;
  426.  
  427. (************************************************************************)
  428. (* MainMenu stellt das Hauptmenü zur Verfügung. Das Hauptmenü wird in   *)
  429. (* der untersten Zeile des Bildschirms dargestellt; auf Wunsch ist ein  *)
  430. (* Hilfsbildschirm verfügbar.                                           *)
  431. PROCEDURE MainMenu;
  432. VAR Key,i : INTEGER;
  433.     H     : PStatus;
  434.     t     : TEXT;
  435.     Zeile : STRING;
  436.     Saved : BOOLEAN;
  437. BEGIN
  438.   REPEAT
  439.     SaveGroundLine;
  440.     GotoXY(1,25);
  441.     Write('F1-Help   F2-Speichern   F3-Laden   F4-Play   F5-Edit   F6-Neustart   F10-Ende');
  442.     REPEAT
  443.       Key := GetKey;
  444.     UNTIL (Key >= 1059) AND (Key <= 1068);
  445.     RestoreGroundLine;
  446.     CASE Key OF
  447.       1059 : Help;
  448.       1060 : BEGIN
  449.                H := SaveState(CtrlMode);
  450.                WHILE KeyPressed DO i := GetKey;
  451.                GotoXY(1,25);
  452.                Write('Speichern Dateiname : ');
  453.                ReadLn(Zeile);
  454.                IF SaveSession(Zeile) THEN
  455.                  Saved := TRUE;
  456.                RestoreState(H,CtrlMode);
  457.                Dispose(H);
  458.              END;
  459.       1061 : BEGIN
  460.                H := SaveState(CtrlMode);
  461.                WHILE KeyPressed DO i := GetKey;
  462.                GotoXY(1,25);
  463.                Write('Laden Dateiname : ');
  464.                ReadLn(Zeile);
  465.                RestoreState(H,CtrlMode);
  466.                Dispose(H);
  467.                IF LoadSession(Zeile) THEN
  468.                  Saved := TRUE;
  469.              END;
  470.       1062 : PlaySession;
  471.       1063 : BEGIN
  472.                EditSession;
  473.                Saved := FALSE;
  474.              END;
  475.       1064 : ClearSession;
  476.     END;
  477.   UNTIL Key = 1068;
  478.   TextColor(LightGray);
  479.   TextBackground(Black);
  480.   IF NOT Saved THEN BEGIN
  481.     REPEAT
  482.       GotoXY(1,25);
  483.       Write('Session nicht abgespeichert, Name : ');
  484.       ReadLn(Zeile);
  485.       IF Zeile <> '' THEN BEGIN
  486.         IF SaveSession(Zeile) THEN
  487.           Saved := TRUE;
  488.       END ELSE
  489.         Saved := TRUE;
  490.     UNTIL Saved;
  491.   END;
  492. END;
  493.  
  494. VAR D1, D2 : STRING;
  495. BEGIN
  496.   FSplit(ParamStr(0),ProgPath,D1,D2);
  497.   InitStack;
  498.   CtrlMode := FALSE;
  499.   CharLast := 0;
  500.   ClearSession;
  501.   InitScreen;
  502.   MainMenu;
  503.   TextColor(Black);
  504.   TextBackground(LightGray);
  505.   ClrScr;
  506.   Write;
  507. END.
  508.  
  509.