home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1988 / 10_11 / coninput.pas < prev    next >
Pascal/Delphi Source File  |  1988-06-24  |  17KB  |  506 lines

  1. (* ------------------------------------------------------ *)
  2. (*                     CONINPUT.PAS                       *)
  3. (*   Komfortable Eingabe für alle Turbo-Pascal-Basistypen *)
  4. (*                   über die Konsole                     *)
  5. (*       (c) 1988 by Karsten Gieselmann  &  TOOLBOX       *)
  6. (*                                                        *)
  7. (* Die UNIT implementiert einen  vollständigen Satz von   *)
  8. (* Routinen zur Eingabe von Variablen des Typs BYTE,      *)
  9. (* SHORTINT, CHAR, INTEGER, WORD, LONGINT, REAL und       *)
  10. (* STRING über die Konsole.  Zum Einlesen der Zeichen-    *)
  11. (* ketten dient ein komfortabler Zeileneditor, der bei    *)
  12. (* frei wählbarer Breite des Eingabefensters auch hori-   *)
  13. (* zontales Scrolling erlaubt;  Fenstertechnik            *)
  14. (* (Window-Befehl aus CRT) wird unterstützt. Leereingaben *)
  15. (* und Abbruch einer Eingabe mittels <Esc> lassen den     *)
  16. (* Inhalt einer einzulesenden Variablen (außer bei        *)
  17. (* STRINGs) unverändert. Editierbefehle:                  *)
  18. (*                                                        *)
  19. (*  <Pfeil links> . Cursor ein Zeichen nach links         *)
  20. (*  <Pfeil rechts>  Cursor ein Zeichen nach rechts        *)
  21. (*  <Ctrl><links> . Cursor ein Wort nach links            *)
  22. (*  <Ctrl><rechts>  Cursor ein Wort nach rechts           *)
  23. (*  <Home> ........ Cursor an den Anfang der Eingabezeile *)
  24. (*  <End> ......... Cursor an das Ende der Eingabezeile   *)
  25. (*  <Del> ......... Zeichen unter Cursor löschen          *)
  26. (*  <Backspace> ... Zeichen links vom Cursor löschen      *)
  27. (*  <Ctrl><Home> .. löschen von Zeilenanfang bis Cursor   *)
  28. (*  <Ctrl><End> ... löschen vom Cursor bis Zeilenende     *)
  29. (*  <PgDn> ........ letzte Eingabe wiederholen            *)
  30. (*  <Ins> ......... Einfügemodus an/aus                   *)
  31. (*  <Esc> ......... Eingabe abbrechen (nicht übernehmen)  *)
  32. (*  <Ctrl><Break> . laufendes Programm abbrechen          *)
  33. (*  <Return> ...... Eingabe beenden (übernehmen)          *)
  34. (*                                                        *)
  35. (* ------------------------------------------------------ *)
  36.  
  37. UNIT ConInput;
  38.  
  39. INTERFACE USES Crt, Dos;
  40.  
  41. (* ----------------  Kontrollvariablen  ----------------- *)
  42.  
  43. VAR EditOld : BOOLEAN; (* bestimmt, ob der alte           *)
  44.                        (* Variablenwert bei der Eingabe   *)
  45.                        (* vorgegeben wird                 *)
  46. VAR InsMode : BOOLEAN; (* bestimmt, ob bei Eingabebeginn  *)
  47.                        (* Insert- oder Overwrite-Modus    *)
  48.                        (* aktiv ist                       *)
  49. VAR BufLen  : BYTE;    (* bestimmt die Maximallänge       *)
  50.                        (* einer Eingabe                   *)
  51. VAR EditSize: BYTE;    (* bestimmt die Breite des         *)
  52.                        (* Editierfeldes                   *)
  53. VAR Aborted : BOOLEAN; (* gibt an, ob die letzte Eingabe  *)
  54.                        (* mit <Esc> oder <Break>          *)
  55.                        (* abgebrochen wurde               *)
  56. VAR Width   : BYTE;    (* bestimmt die Breite, mit der    *)
  57.                        (* eine  REAL-Variable im  Gleit-  *)
  58.                        (* kommaformat vorgegeben wird;    *)
  59.                        (* beim Festkommadarstellung hat   *)
  60.                        (* diese Größe keinen Einfluß auf  *)
  61.                        (* das Anzeigeformat eines         *)
  62.                        (* REAL-Wertes!                    *)
  63.  
  64. VAR Decimals: SHORTINT;
  65.                        (* legt die Anzahl der Nachkomma-  *)
  66.                        (* stellen bei der Eingabevorgabe  *)
  67.                        (* für REAL-Variablen fest; Angabe *)
  68.                        (* eines Wertes < 0 bewirkt        *)
  69.                        (* Gleitkommadarstellung!          *)
  70.  
  71.  
  72. (* ---------  Eingaberoutinen für die Basistypen  ------- *)
  73.  
  74. PROCEDURE ReadByte (VAR B : BYTE);
  75.                          (* Einlesen einer BYTE-Variablen *)
  76.  
  77. PROCEDURE ReadShortInt (VAR S : SHORTINT);
  78.                  (* Einlesen einer ShortInteger-Variablen *)
  79.  
  80. PROCEDURE ReadChar (VAR C :CHAR);
  81.                     (* Einlesen einer Character-Variablen *)
  82.  
  83. PROCEDURE ReadInt (VAR I :INTEGER);
  84.                       (* Einlesen einer INTEGER-Variablen *)
  85.  
  86. PROCEDURE ReadLongInt (VAR L :LONGINT);
  87.                   (* Einlesen einer LongInteger-Variablen *)
  88.  
  89. PROCEDURE ReadWord (VAR W :WORD);
  90.                          (* Einlesen einer WORD-Variablen *)
  91.  
  92. PROCEDURE ReadReal (VAR R :REAL);
  93.                    (* Einlesen einer Gleitkomma-Variablen *)
  94.  
  95. PROCEDURE ReadString (VAR S : STRING);
  96.                        (* Einlesen einer STRING-Variablen *)
  97.  
  98.  
  99.  
  100. IMPLEMENTATION
  101.  
  102.  
  103. (* ------- Akustische Fehlermeldung durch Piepton ------- *)
  104.  
  105. PROCEDURE Beep (Frequency, Hold : WORD);
  106. BEGIN
  107.   Sound (Frequency); Delay (Hold); NoSound
  108. END;
  109.  
  110. (* ---------------  der Zeileneditor -------------------- *)
  111.  
  112. PROCEDURE EditString (VAR EditStr : STRING; MaxLen : BYTE);
  113.  
  114. TYPE
  115.   ShapeType = ARRAY [FALSE..TRUE] OF WORD;
  116.  
  117. CONST
  118.   Monochrome = 7;
  119.   MonoShape  : ShapeType = ($0C0D, $060D);
  120.   ColorShape : ShapeType = ($0607, $0407);
  121.   Letters    : SET OF CHAR = ['A'..'Z','a'..'z','0'..'9',
  122.                               'ß','Ä','Ö','Ü','ä','ö','ü'];
  123.  
  124. VAR
  125.   xpos,ypos,Deleted         : INTEGER;
  126.   p,f,w,SaveShape,Command   : WORD;
  127.   c                         : CHAR absolute Command;
  128.   CursorShape               : WORD absolute $0040:$0060;
  129.   VideoMode                 : BYTE absolute $0040:$0049;
  130.   First,Quit,Display,Insert : BOOLEAN;
  131.   s                         : STRING;
  132.   Len                       : BYTE absolute s;
  133.   Shape                     : ShapeType;
  134.  
  135. PROCEDURE SetCursorShape (Shape :WORD);
  136.                                      (* Setzt Cursorgröße *)
  137.   INLINE ($59/$B4/$01/$CD/$10);
  138.  
  139. FUNCTION GetKey :WORD;
  140.                    (* wartet auf Taste und holt Scan-Code *)
  141.   INLINE ($31/$C0/$CD/$16);
  142.  
  143. FUNCTION MinI (a,b :INTEGER) :INTEGER;
  144.                            (* liefert Minimum von a und b *)
  145.   INLINE ($58/$5B/$39/$D8/$7E/$02/$89/$D8);
  146.  
  147. PROCEDURE Cursor (Switch : BOOLEAN);
  148.                                 (* schaltet Cursor an/aus *)
  149. BEGIN
  150.   CASE Switch OF
  151.     TRUE:  SetCursorShape (CursorShape AND $EFFF);
  152.     FALSE: SetCursorShape (CursorShape  OR $1000);
  153.   END;
  154. END;
  155.  
  156. FUNCTION StringOf (Ch : CHAR; Num : INTEGER) : STRING;
  157.                                        (* String aus "Ch" *)
  158. VAR s : STRING;
  159. BEGIN
  160.   IF Num < 0 THEN Num:=0;
  161.   s[0] := Chr (Num);
  162.   FillChar (s[1], Num, Ch);
  163.   StringOf := s;
  164. END;
  165.  
  166. PROCEDURE PosCursor (p : WORD);
  167.                    (* setzt Cursor auf Stringposition "p" *)
  168. BEGIN
  169.   GotoXY(Succ(Pred(xpos+p-f) MOD w), ypos
  170.                                   + (Pred(xpos+p-f) DIV w));
  171. END;
  172.  
  173. PROCEDURE Advance (StepForward : BOOLEAN);
  174.                      (* bewegt den Cursor im STRING um    *)
  175.                      (* eine Position nach links / rechts *)
  176.                      (* und berechnet gegebenfalls die    *)
  177.                      (* neue Lage des Strings im          *)
  178.                      (* Editierfenster                    *)
  179. BEGIN
  180.   IF StepForward THEN BEGIN
  181.     IF (p > f+EditSize-2) THEN Inc(f) ELSE Display:=FALSE;
  182.     Inc(p);
  183.   END ELSE BEGIN
  184.     IF p = f THEN Dec(f) ELSE Display:=FALSE;
  185.     Dec (p);
  186.   END;
  187. END;
  188.  
  189. BEGIN                                       (* EditString *)
  190.   xpos       := WhereX;           (* Home-Position merken *)
  191.   ypos       := WhereY;
  192.   w          := Lo(WindMax) - Lo(WindMin) + 1;
  193.                                  (* nutzbare Schirmbreite *)
  194.   s          := EditStr;
  195.   p          := 1;           (* Cursor-Position im STRING *)
  196.   f          := 1;           (* STRING-Index des ersten   *)
  197.                              (* angezeigten Zeichens      *)
  198.   Deleted    := 0;
  199.   First      := TRUE;
  200.   Quit       := FALSE;       (* Flagbyte für Eingabe      *)
  201.                              (* abgeschlossen             *)
  202.   Aborted    := FALSE;
  203.   Insert     := InsMode;     (* Flagbyte für Einfügemodus *)
  204.                              (* an/aus                    *)
  205.   Display    := TRUE;
  206.   SaveShape  := CursorShape;
  207.   If VideoMode = Monochrome THEN
  208.     Shape := MonoShape
  209.   ELSE
  210.     Shape := ColorShape;
  211.   SetCursorShape (Shape[Insert]);
  212.   REPEAT
  213.     IF p > Len THEN IF Deleted=0 THEN Deleted:=1;
  214.     IF Display THEN BEGIN
  215.       Cursor (FALSE);
  216.       GotoXY (xpos,ypos);
  217.       Write (Copy(s,f,EditSize) + StringOf(' ',Deleted));
  218.       Cursor (TRUE);
  219.     END;
  220.     Display := TRUE;
  221.     Deleted := 0;
  222.     PosCursor (p);
  223.     Command := GetKey;
  224.     CASE Command OF
  225.  
  226.       $4B00:                                   (* <Left>  *)
  227.         IF p>1 THEN Advance (FALSE);
  228.  
  229.       $4D00:                                   (* <Right> *)
  230.         IF p<=Len THEN Advance (TRUE);
  231.  
  232.       $7300:                              (* <Ctrl><Left> *)
  233.         BEGIN
  234.           WHILE (p>1) AND NOT (s[p-1] IN Letters) DO
  235.             Advance (FALSE);
  236.           WHILE (p>1) AND     (s[p-1] IN Letters) DO
  237.             Advance (FALSE);
  238.           Display := TRUE;
  239.         END;
  240.  
  241.       $7400:                             (* <Ctrl><Right> *)
  242.         BEGIN
  243.           WHILE (p <= Len) AND     (s[p] IN Letters) DO
  244.             Advance (TRUE);
  245.           WHILE (p <= Len) AND NOT (s[p] IN Letters) DO
  246.             Advance (TRUE);
  247.           Display := TRUE;
  248.         END;
  249.  
  250.       $4700:                                    (* <Home> *)
  251.         BEGIN
  252.           p:=1; f:=1;
  253.         END;
  254.  
  255.       $4F00:                                     (* <End> *)
  256.         BEGIN
  257.           p := Len+1;
  258.           IF p > EditSize THEN
  259.              f := Succ (p-EditSize)
  260.           ELSE
  261.              f := 1;
  262.         END;
  263.  
  264.       $5300:                                     (* <Del> *)
  265.         IF p <= Len THEN BEGIN
  266.           IF Len > EditSize THEN
  267.             IF (f <> 1) AND (p-f <> EditSize) THEN
  268.               Dec (f)
  269.             ELSE
  270.           ELSE
  271.             Deleted := 1;
  272.           Delete (s, p, 1);
  273.         END;
  274.  
  275.       $0E08:                                   (* <BkSpc> *)
  276.         IF p > 1 THEN BEGIN
  277.           IF Len >= EditSize THEN
  278.             IF f <> 1 THEN
  279.               Dec (f)
  280.             ELSE IF Len = EditSize THEN
  281.               Deleted := 1
  282.             ELSE
  283.           ELSE
  284.             Deleted := 1;
  285.           Dec (p);
  286.           Delete (s, p, 1);
  287.         END;
  288.  
  289.       $7700:                              (* <Ctrl><Home> *)
  290.         BEGIN
  291.           Deleted := Pred(MinI(EditSize,Len))
  292.                      - INTEGER(Len-p);
  293.           IF p = Len+1 THEN
  294.             s := ''
  295.           ELSE
  296.             s := Copy (s, p, Len-p+1);
  297.           p:=1; f:=1;
  298.         END;
  299.  
  300.       $7500:                               (* <Ctrl><End> *)
  301.         BEGIN
  302.           IF p > EditSize THEN
  303.             f := Succ (p-EditSize)
  304.           ELSE
  305.             BEGIN
  306.               Deleted := MinI(EditSize,Len) - Pred(p);
  307.               f := 1;
  308.             END;
  309.           Len := p-1;
  310.         END;
  311.  
  312.       $5200:                                     (* <Ins> *)
  313.         BEGIN
  314.           Display := FALSE;
  315.           Insert := NOT Insert;
  316.           SetCursorShape (Shape[Insert]);
  317.         END;
  318.  
  319.       $5100, $011B, $0000:
  320.                           (* <PgDn>, <Esc>, <Ctrl><Break> *)
  321.         BEGIN
  322.           Deleted := Len;
  323.           s := EditStr;
  324.           Deleted := MinI (EditSize-Len, Deleted-Len);
  325.           p:=1; f:=1;
  326.           First := TRUE;
  327.           Aborted := (Command=$0000) OR (Command=$011B);
  328.         END;
  329.  
  330.       $1C0D:                 (* <Return>, Eingabe beenden *)
  331.         Quit := TRUE;
  332.  
  333.       ELSE
  334.         IF Ord(c) >= 32 THEN    (* Eingabe eines Zeichens *)
  335.           IF First THEN BEGIN
  336.             Deleted := Pred (MinI (EditSize,Len));
  337.             s := c;
  338.             p := 2
  339.           END ELSE BEGIN
  340.             IF p = Len+1 THEN          (* hinten anfügen? *)
  341.               IF Len < MaxLen THEN BEGIN
  342.                 s := s + c;
  343.                 Advance (TRUE);
  344.               END ELSE           (* Maximallänge erreicht *)
  345.                 Beep (3200,50)
  346.               ELSE
  347.                 IF NOT Insert THEN BEGIN
  348.                   s[p] := c;
  349.                           (* Cursor-Zeichen überschreiben *)
  350.                   Advance (TRUE);
  351.                 END ELSE
  352.                   IF Len < MaxLen THEN BEGIN
  353.                                               (* einfügen *)
  354.                     s := Copy (s,1,p-1) + c
  355.                          + Copy (s,p,Len);
  356.                     Advance (TRUE);
  357.                   END ELSE       (* Maximallänge erreicht *)
  358.                     Beep (3200,50);
  359.                   Display := TRUE;
  360.                   END
  361.           END;
  362.     IF Command <> $5100 THEN First:=FALSE
  363.   UNTIL Quit OR Aborted;
  364.   EditStr := s;
  365.   f := 1;
  366.   GotoXY (xpos,ypos);
  367.   Write (Copy(s,f,EditSize) + StringOf(' ',Deleted));
  368.   PosCursor (MinI (EditSize,Len+1));
  369.   SetCursorShape (SaveShape);
  370. END;
  371.  
  372.  
  373. (* --------  Eingaberoutinen für die Basistypen  -------- *)
  374.  
  375. TYPE
  376.   Type_ = (BYTE_, SHORTINT_, INTEGER_, WORD_,
  377.            LONGINT_, REAL_);
  378.  
  379. PROCEDURE Read (p :POINTER; t :Type_);
  380.                           (* liest die bei "p^" stehenden *)
  381.                           (* Variablen vom Typ "t" ein    *)
  382. VAR
  383.   St,Old   : STRING;
  384.   ErrorPos : INTEGER;
  385.   x,y      : BYTE;
  386.   New      : RECORD CASE Type_ OF
  387.                0: (B : BYTE);
  388.                1: (S : SHORTINT);
  389.                2: (I : INTEGER);
  390.                3: (W : WORD);
  391.                4: (L : LONGINT);
  392.                5: (R : REAL);
  393.              END;
  394.  
  395. BEGIN
  396.   x := WhereX;
  397.   y := WhereY;
  398.   WITH New DO BEGIN
  399.     CASE t OF
  400.       BYTE_     : BEGIN  B := BYTE(p^);      Str(B,Old) END;
  401.       SHORTINT_ : BEGIN  S := SHORTINT(p^);  Str(S,Old) END;
  402.       INTEGER_  : BEGIN  I := INTEGER(p^);   Str(I,Old) END;
  403.       WORD_     : BEGIN  W := WORD(p^);      Str(W,Old) END;
  404.       LONGINT_  : BEGIN  L := LONGINT(p^);   Str(L,Old) END;
  405.       ELSE BEGIN
  406.         R := REAL (p^);
  407.         IF Decimals > 0 THEN          (* Fixkomma-Format? *)
  408.           Str (R:0:Decimals, Old)
  409.         ELSE BEGIN                   (* Gleitkomma-Format *)
  410.           Str (R,Old);
  411.           IF Length(Old) < Width THEN
  412.             Width := Length (Old);
  413.           Str (R:Width+1, Old);
  414.         END;
  415.         WHILE Old[1]=' ' DO Delete (Old,1,1);
  416.                                 (* Leerzeichen abstreifen *)
  417.       END
  418.     END;
  419.     IF EditOld THEN St:=Old ELSE St:='';
  420.     REPEAT
  421.       GotoXY (x,y);
  422.       EditString (St, BufLen);
  423.       IF St='' THEN St:=Old;
  424.       IF t = REAL_ THEN
  425.         Val (St, R, ErrorPos)
  426.       ELSE BEGIN
  427.         Val (St, L, ErrorPos);
  428.         IF ErrorPos = 0 THEN
  429.           CASE t OF
  430.             BYTE_    : IF (L <     0) OR (L >   255) THEN
  431.                          ErrorPos:=1;
  432.             SHORTINT_: IF (L <  -128) OR (L >   127) THEN
  433.                          ErrorPos:=1;
  434.             INTEGER_ : IF (L <-32768) OR (L > 32767) THEN
  435.                          ErrorPos:=1;
  436.             WORD_    : IF (L <     0) OR (L > 65535) THEN
  437.                          ErrorPos:=1;
  438.           END;
  439.       END;
  440.       IF ErrorPos > 0 THEN Beep(500,100);
  441.     UNTIL ErrorPos = 0;
  442.     CASE t OF
  443.       BYTE_    : BYTE(p^)     := B;
  444.       SHORTINT_: SHORTINT(p^) := S;
  445.       INTEGER_ : INTEGER(p^)  := I;
  446.       WORD_    : WORD(p^)     := W;
  447.       LONGINT_ : LONGINT(p^)  := L;
  448.       REAL_    : REAL(p^)     := R
  449.       END
  450.     END;
  451. END;
  452.  
  453. PROCEDURE ReadByte (VAR B : BYTE);
  454. BEGIN
  455.   Read (@B, BYTE_)
  456. END;
  457.  
  458. PROCEDURE ReadShortInt (VAR S : SHORTINT);
  459. BEGIN
  460.   Read (@S, SHORTINT_)
  461. END;
  462.  
  463. PROCEDURE ReadChar (VAR C : CHAR);
  464. VAR
  465.   S : STRING;
  466. BEGIN
  467.   EditString (S, 1);
  468.   C := S[1];
  469. END;
  470.  
  471. PROCEDURE ReadInt (VAR I : INTEGER);
  472. BEGIN
  473.   Read (@I, INTEGER_)
  474. END;
  475.  
  476. PROCEDURE ReadLongInt (VAR L :LONGINT);
  477. BEGIN
  478.   Read (@L, LONGINT_)
  479. END;
  480.  
  481. PROCEDURE ReadWord (VAR W : WORD);
  482. BEGIN
  483.   Read (@W, WORD_)
  484. END;
  485.  
  486. PROCEDURE ReadReal (VAR R : REAL);
  487. BEGIN
  488.   Read (@R, REAL_)
  489. END;
  490.  
  491. PROCEDURE ReadString (VAR S : STRING);
  492. BEGIN
  493.   EditString (S, BufLen);
  494. END;
  495.  
  496. BEGIN
  497.   EditOld  := TRUE;          (* Vorgaben standardmäßig an *)
  498.   InsMode  := TRUE;      (* Einfügemodus standardmäßig an *)
  499.   Width    := 255;
  500.   Decimals :=  20;  (* Fließkomma-Format bei REAL-Eingabe *)
  501.   BufLen   := 255;  (* Voreinstellung: maximale Länge     *)
  502.   EditSize := 255;
  503.   Aborted  := FALSE;
  504. END.
  505. (* ------------------------------------------------------ *)
  506. (*                 Ende von CONINPUT.PAS                  *)