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. |