Home Programmierung
und BIOS
Shareware-
FAQ
Kontakt u.
Infos

Pascal-Toolbox Nr. 2

Verbesserte Eingabefunktion (DOS)

Die zweite Folge meiner Toolbox wird sich mit einer Möglichkeit beschäftigen, die Eingabe komfortabler zu gestalten.

Manchmal ist es nötig, daß man Eingaben flexibler gestaltet. Z.B. soll manchmal Text vorgegeben werden, der editiert werden kann, oder es soll eine Maximallänge angegeben werden können. Auch ist eine komfortablere Steuerung des Cursors (z.B. Unterstützung von Pos1, Entf., Ende) oft hilfreich.


Für alle, die nicht (mehr) so fit in der Unit-Programmierung sind, zuerst einmal das Grundgerüst unserer Unit:

 

UNIT Input;

INTERFACE

CONST iNormal=0;

      iZahl=1;

      iGeheim=2;

      iGross=3;

      iKlein=4;

FUNCTION Stringer (Texter:String;Lang,Typ:Integer):String;

IMPLEMENTATION

USES Crt;

FUNCTION Stringer (Texter:String;Lang,Typ:Integer):String;

{...} 

END.

Zuerst wird der Name der Unit (INPUT) angegeben. Dieser muß mit dem Namen der Datei übereinstimmen (INPUT.PAS).

Als nächstes folgen unter INTERFACE alle öffentlichen Funktionen und Definitionen. In diesem Fall haben wir die Funktion Stringer, die wir noch weiter unten behandeln, öffentlich deklariert (d.h. von außen kann darauf zugegriffen werden). Außerdem die fünf Konstanten für den Modus der Funktion (Normal, nur Zahlen, Passwort, Großbuchstaben, Kleinbuchstaben).

Als nächstes folgt dann die Definition der eigentlichen Funktion im Bereich IMPLEMENTATION der am Ende mit END. abgeschlossen sein muß.

Wenden wir uns nun der Funktion zu:


FUNCTION Stringer (Texter:String;Lang,Typ:Integer):String;

VAR Eingabe:Char;  

    OldStr:String; 

    Posi:Integer;  

    X:Integer;     

    Y:Integer;     

    I:Integer;     

    Ende:Boolean;  

    Flag:Boolean;  

Der Funktion werden 3 Parameter übergeben: TEXTER ist ein String, der normalerweise nichts enthält. Jedoch kann es manchmal notwendig sein, daß der User bestimmte Strings verändern kann. In diesem Fall wird der entsprechende String hier übergeben. LANG gibt die maximale Länge der eingegebenen Zeichenkette an und TYP schließlich den Modus, in dem die Eingabe erfolgt (s.o.).

Die Variablen: EINGABE enthält den jeweils ermittelten Tastendruck, OLDSTR den anfänglichen Inhalt von TEXTER (wird bei einem Abbruch mit ESC zurückgeliefert). Posi gibt die aktuelle Position des Cursors relativ zu X an. X gibt die X-Achsen-Koordinate, Y die Y-Achsen-Koordinate des Textanfanges wieder. I ist eine Allround-Variable, sie wird u.a. für die zahlreichen FOR-Schleifen in der Funktion benötigt. ENDE ist anfänglich FALSE und wird nur bei einem Druck auf ENTER oder ESC gesetzt, um das Funktionsende zu signalisieren (äußere REPEAT-Schleife). FLAG schließlich gibt an, ob der letzte Tastendruck einen erweiterten Code besaß (#0 + #??).


BEGIN

  Ende:=false;

  OldStr:=Texter;

  Posi:=Length(Texter);

  X:=WhereX;

  Y:=WhereY;

  GotoXY (X,Y);

  IF Typ<>iGeheim THEN Write (Texter)

  ELSE FOR I:=1 TO Length(Texter) DO Write ('*');

Hier erfolgen die allgemeinen Vorbereitungen: ENDE wird auf FALSE gesetzt, OLDSTR speichert den alten Inhalt von TEXTER, Posi wird so gesetzt, daß der Cursor am Ende des Textes steht, die Achsenabschnitte werden bestimmt und dann der Inhalt von Texter (falls schon vorhanden) dargestellt. Wurde der Passwortmodus (Typ=iGeheim) aktiviert, werden stattdessen die entsprechende Zahl an Sternchen ausgegeben.


  REPEAT

    Eingabe:=ReadKey; Flag:=False;

    IF Eingabe=#0 THEN BEGIN

      Flag:=True; Eingabe:=ReadKey; END;

Nun wird die REPEAT-Schleife betreten. Als erstes wird auf einen Tastendruck gewartet (ReadKey). Als nächstes wird dann überprüft, ob eventuell ein erweiterter Tastencode vorliegt. In diesem Fall liefert Readkey #0. Ist dies der Fall, setzen wir FLAG und fragen den erweiterten Tastencode durch erneuten Aufruf von Readkey ab. Erweiterte Tastencodes treten z.B. beim Druck auf die Cursortasten oder die F#-Tasten auf.

Als nächstes müssen nur noch die Tastencodes ausgewertet werden:


    IF (Flag=True) AND (Eingabe=#75) THEN BEGIN

      IF Posi>0 THEN BEGIN

        Posi:=Posi-1;

        GotoXY (X+Posi,Y);

      END;

    END

Hier wird auf den Druck der Taste Cursor-Links reagiert. Befindet sich der Cursor noch nicht ganz links (Posi<>0), wird er eine Stelle weiter links positioniert.


    ELSE IF (Flag=True) AND (Eingabe=#77) THEN BEGIN

      IF Posi<Length(Texter) THEN BEGIN

        Posi:=Posi+1;

        GotoXY (X+Posi,Y);

      END;

    END

Hier wird auf den Druck der Taste Cursor-Rechts reagiert. Befindet sich der Cursor noch nicht am Ende der Eingabe (Posi<Length(Texter)), wird er eine Stelle weiter rechts positioniert.


    ELSE IF (Flag=True) AND (Eingabe=#83) THEN BEGIN {Entf. gedrückt}

      Delete (Texter,Posi+1,1);

      GotoXY (X+Posi,Y);

      IF Typ<>iGeheim THEN For I:=Posi+1 TO Length(Texter) DO Write (Texter[i])

      ELSE FOR I:=Posi+1 TO Length(Texter) DO Write ('*');

      Write (' ');

      GotoXY (X+Posi,Y);

    END

Hier wird auf den Druck der Taste Entf. (oder auch Del) reagiert. Es wird nun der Buchstabe an der nächsten Position rechts vom Cursor gelöscht (wenn vorhanden). Eine Fehlerabfrage ist beim Aufruf von Delete nicht notwendig, da Delete automatisch das Löschen außerhalb des gültigen Stringbereiches unterbindet.

Als nächstes wird dann der gekürzte Text dargestellt (auf die bekannte Weise), das übrig gebliebene Zeichen auf dem Bildschirm gelöscht und der Cursor neu positioniert.


    ELSE IF (Flag=False) AND (Eingabe=#8) THEN BEGIN

      Delete (Texter,Posi,1);

      IF Posi<>0 THEN Posi:=Posi-1;

      GotoXY (X+Posi,Y);

      IF Typ<>iGeheim THEN For I:=Posi+1 TO Length(Texter) DO Write (Texter[i])

      ELSE FOR I:=Posi+1 TO Length(Texter) DO Write ('*');

      Write (' ');

      GotoXY (X+Posi,Y);

    END

Hier wird auf den Druck der Taste Backspace reagiert. Es wird nun der Buchstabe an der nächsten Position links vom Cursor gelöscht (wenn vorhanden). Eine Fehlerabfrage ist beim Aufruf von Delete nicht notwendig, da Delete automatisch das Löschen außerhalb des gültigen Stringbereiches unterbindet. Da aber beim Drücken der Backspace-Taste der Cursor immer um eine Stelle nach links rückt, muß (a) Posi dekrementiert werden und (b) eine Sicherheitsabfrage, ob Posi=0 ist, erfolgen. Die nun folgenden Schritte entsprechen den weiter oben genannten.


    ELSE IF (Flag=True) AND (Eingabe=#71) THEN BEGIN

      Posi:=0;

      GotoXY (X,Y);

    END

Hier wird auf den Druck der Taste Pos1 reagiert. Posi wird gleich null gesetzt und der Cursor an den Anfang (X,Y) gesetzt.


    ELSE IF (Flag=True) AND (Eingabe=#79) THEN BEGIN

      Posi:=Length(Texter);

      GotoXY (X+Posi,Y);

    END

Hier wird auf den Druck der Taste Ende reagiert. Posi wird gleich Length(Texter) gesetzt und der Cursor an das Ende (X+Length(Texter),Y) gesetzt.


    ELSE IF (Flag=False) AND (Eingabe=#13) THEN BEGIN

      Stringer:=Texter;

      Ende:=true;

    END

Hier wird auf den Druck der Taste Enter reagiert. Zuerst wird dem Rückgabewert der Funktion der Inhalt von TEXTER zugewiesen. Dann wird ENDE gesetzt, um die Schleife zu beenden.


    ELSE IF (Flag=False) AND (Eingabe=#27) THEN BEGIN

      Stringer:=OldStr;

      Ende:=true;

    END

Hier wird auf den Druck der Taste Escape reagiert. Zuerst wird dem Rückgabewert der Funktion der Inhalt von OLDSTR zugewiesen. D.h. in der Regel wird '' zurückgeliefert (außer, TEXTER wurde am Anfang mit einem abweichenden String belegt). Dann wird ENDE gesetzt, um die Schleife zu beenden.


    ELSE IF ((Flag=False) AND (Eingabe=#9)) OR ((Flag=True) AND (Eingabe IN [#15,

    #59..#68,#71..#73,#80..#82,#84..#113,#115..#119,#132,#160,#164,#175,#178,#180,

    #182,#183])) THEN BEGIN END

Hier werden eventuell störende Zeichen, die nur Wirr-Warr auf dem Bildschirm produzieren würden, herausgefiltert.


    ELSE BEGIN

      IF Length(Texter)<Lang THEN BEGIN

        CASE Typ OF

          iGross: BEGIN

            Eingabe:=UpCase (Eingabe);

            CASE Eingabe OF

              'ä': Eingabe:='Ä';

              'ü': Eingabe:='Ü';

              'ö': Eingabe:='Ö';

            END;

          END;

          iKlein: BEGIN

            CASE Eingabe OF

              'A'..'Z': Eingabe:=Chr(Ord(Eingabe)+32);

              'ä': Eingabe:='Ä';

              'ü': Eingabe:='Ü';

              'ö': Eingabe:='Ö';

            END;

          END;

        END;

        IF (Typ<>iZahl) OR ((Typ=iZahl) AND (Eingabe IN ['0'..'9'])) THEN BEGIN

          Insert (Eingabe,Texter,Posi+1);

          Posi:=Posi+1;

          GotoXY (X+Posi-1,Y);

          IF Typ<>iGeheim THEN For I:=Posi TO Length(Texter) DO Write (Texter[i])

          ELSE FOR I:=Posi TO Length(Texter) DO Write ('*');

          GotoXY (X+Posi,Y);

        END;

      END;

    END;

  UNTIL Ende=true;

END;

Jetzt endlich haben wir die puren Buchstaben und können nun mit dem Einfügen beginnen. Zuvor muß jedoch noch der Modus überprüft werden, ob der Buchstabe in einen Großbuchstaben oder Kleinbuchstaben umgewandelt werden soll. Ist dies der Fall, wird es getan. Dann wird überprüft, ob der Modus Nur Zahlen gesetzt ist. Ist dies der Fall und der Buchstabe liegt außerdem im gültigen Bereich wird der Buchstabe eingefügt. Dies erfolgt außerdem, wenn keine Einschränkung auf Zahlen eingestellt ist.

Angewandt wird die Funktion wie folgt:


  USES INPUT;

  {...}

  BEGIN

    {...}

    Test:=Stringer('',25,iNormal);

    {...}

  END.

Für Interessierte habe ich eine Tabelle mit allen Tastencodes zusammengestellt.

Die fertige Unit (ca. 2 KB) könnt Ihr hier downloaden.

Alle Angaben ohne Gewähr.

Achtung: bitte Hinweise zur Aktualitšt der Daten beachten! Copyright