SWAGOLX.EXE (c) 1993 GDSOFT ALL RIGHTS RESERVED 00009 INPUT AND FIELD ENTRY ROUTINES 1 05-31-9308:59ALL GAYLE DAVIS Simple Field Input IMPORT 23 usesπ crt;πtypeπ input_data = recordπ st : string; { The string to be input }π col,row, { position of input }π attr, { color of input }π flen : byte; { maximum length of input }π prompt : string[40];π end;πconstπ NumberOfFields = 3;π BackSpace = $08;π Enter = $0d;π Escape = $1b;π space = $20;ππvarπ InputField : array[1..NumberOfFields] of input_data;π x : byte;π Done : boolean;π field : byte;πππProcedure SetInputField(VAR inpRec : Input_data;π S : STRING;π C,R : Byte;π A,L : Byte;π P : String);ππBEGINπWith inpRec DOπ BEGINπ St := S;π Col := C;π Row := R;π Attr := A;π fLen := L;π Prompt := P;π END;πEND;πππprocedure GetStr(var inprec: input_data; var f: byte; var finished: boolean);π varπ spstr : string; { just a string of spaces }π x,y,π oldattr: byte;π ch : char;π chval : byte absolute ch;π len : byte absolute inprec;π beginπ with inprec do beginπ FillChar(spstr,sizeof(spstr),32); spstr[0] := chr(flen);π y := row; x := col + length(prompt);π oldattr := TextAttr; finished := false;π gotoXY(col,row); write(prompt);π TextAttr := attr;π repeatπ gotoXY(x,y); write(st,copy(spstr,1,flen-len)); gotoXY(x+len,y);π ch := ReadKey;π case chval ofπ 0 : ch := ReadKey;π Enter : beginπ inc(f);π if f > NumberOfFields then f := 1;π TextAttr := oldattr;π exit;π end;π BackSpace : if len > 0 thenπ dec(len);π Escape : begin { the escape key is the only way to halt }π finished := true;π TextAttr := oldattr;π exit;π end;π 32..255 : if len <> flen then beginπ inc(len);π st[len] := ch;π end;π end; { case }π until false; { procedure only exits via exit statements }π end; { with }π end; { GetStr }ππbeginπ Clrscr;π SetInputField(InputField[1],'',12,10,31,20,'Your Name : ');π SetInputField(InputField[2],'',12,11,31,20,'Your Address : ');π SetInputField(InputField[3],'',12,12,31,20,'City,State : ');π field := 1;π repeatπ GetStr(InputField[field],field,Done);π until Done;πend.π 2 06-08-9308:24ALL SWAG SUPPORT TEAM General Input with Color IMPORT 18 { General STRING input routine with Color prompt and input }ππUSES DOS,Crt;ππTYPEπ CharSet = Set OF Char;ππVARπ Name : STRING;ππprocedure QWrite( Column, Line , Color : byte; S : STRING );ππvarπ VMode : BYTE ABSOLUTE $0040 : $0049; { Video mode: Mono=7, Color=0-3 }π NumCol : WORD ABSOLUTE $0040 : $004A; { Number of CRT columns (1-based) }π VSeg : WORD;π OfsPos : integer; { offset position of the character in video RAM }π vPos : integer;π sLen : Byte ABSOLUTE S;ππBeginπ If VMode in [0,2,7] THEN VSeg := $B000 ELSE VSeg := $B800;π OfsPos := (((pred(Line) * NumCol) + pred(Column)) * 2);π FOR vPos := 0 to pred(sLen) doπ MemW[VSeg : (OfsPos + (vPos * 2))] :=π (Color shl 8) + byte(S[succ(vPos)])πEnd;ππFunction GetString(cx,cy,cc,pc : Byte; Default,Prompt : String; MaxLen : Integer;OKSet :πcharset):string;ππ{ cx = Input Column }π{ cy = Input Row }π{ cc = Input Color }π{ pc = Prompt Color }ππconstπ BS = ^H;π CR = ^M;π iPutChar = #249;π ConSet : CharSet = [BS,CR];πvarπ TStr : string;π TLen,X,i : Integer;π Ch : Char;πbeginπ {$I-} { turn off I/O checking }π TStr := '';π TLen := 0;π Qwrite(cx,cy,pc,Prompt);π X := cx + Length(Prompt);π For i := x to (x + Maxlen - 1) doπ Qwrite(i,cy,cc,iputChar);π Qwrite(x,cy,cc,Default);π OKSet := OKSet + ConSet;π repeatπ Gotoxy(x,cy);π repeatπ ch := readkeyπ until Ch in OKSet;π if Ch = BS then beginπ if TLen > 0 then beginπ TLen := TLen - 1;π X := X - 1;π QWrite(x,cy,cc,iPutChar);π endπ endπ else if (Ch <> CR) and (TLen < MaxLen) then beginπ QWrite(x,cy,cc,Ch);π TLen := TLen + 1;π TStr[TLen] := Ch;π X := X + 1;π endπ until Ch = CR;π If Tlen > 0π Then Beginπ TStr[0] := chr(Tlen);π Getstring := TStrπ Endπ Else Getstring := Default;π {$I+}πend;πππBEGINπ ClrScr;π Name := Getstring(16,5,79,31,'GOOD OLE BOY','Enter Name : ',25,['a'..'z','A'..'Z',' ']);π GOTOXY(16,7);π WriteLn('Name : ',Name);π Readkey;πEND.ππ 3 06-22-9309:18ALL SWAG SUPPORT TEAM OOP Line Editor IMPORT 49 π{ A good line editor object }ππUNIT EditObj; { Object_Line_Editor }ππINTERFACEππUSES Crt, KeyBd;ππTYPEπ LineEdit = OBJECTπ Pos, XPos, YPos : Integer;π EdLine : String;π PROCEDURE InitEdit( X, Y: Integer; LineIn: String );π FUNCTION GetLine: String;π END;ππVARπ Kbd: KeyBoard; {<<<========== Global definition of OBJECT}ππ{***************************************************************}π IMPLEMENTATIONπ{***************************************************************}ππ{-------------------------------------------------π- Name : InitEdit -π- Purpose: Set up editor, display line onscreen -π-------------------------------------------------}ππPROCEDURE LineEdit.InitEdit;π BEGINπ EdLine := LineIn;π Pos := Ord( LineIn[0] ) + 1;π XPos := X;π YPos := Y;π GotoXY( X, Y );π Write( LineIn );π END;ππ{-------------------------------------------------π- Name : GetLine -π- Purpose: Process keying from user -π- Maximum 80 characters accepted -π-------------------------------------------------}ππFUNCTION LineEdit.GetLine;π VARπ KeyFlags : Byte;π Ch: Char;π FunctKey, Finish: Boolean;π BEGINπ Finish := FALSE;π REPEATπ IF Kbd.GetKey( KeyFlags, FunctKey, Ch ) THEN BEGINπ IF FunctKey THENπ CASE Ch OFπ{ HOME } #$47: Pos := 1;π{ END } #$4F: Pos := Ord( EdLine[0] ) + 1;π{ RIGHT } #$4D: BEGINπ IF Pos < 80 THEN Inc( Pos );π IF Pos > Ord( EdLine[0] ) THENπ Insert( ' ', EdLine, Pos );π END;π{ LEFT } #$4B: IF Pos > 1 THEN Dec( Pos );π{ DELETE } #$53: IF Pos <= Ord( EdLine[0] ) THENπ Delete( EdLine, Pos, 1 );π END {CASE Ch}π ELSE {IF}π CASE Ch OFπ{ BS } #$08: IF Pos > 1 THEN BEGINπ Delete( EdLine, Pos-1, 1 );π Dec( Pos );π END;π{ ENTER } #$0D: Finish := TRUE;π ELSE BEGINπ IF( ( KeyFlags AND $80 ) <> $80 )π THEN Insert( Ch, EdLine, Pos )π ELSE EdLine[Pos] := Ch;π IF Pos > Ord( EdLine[0] ) THENπ EdLine[0] := Chr( Pos );π IF Pos < 80 THEN Inc( Pos );π END {CASE CH ELSE}π END; {CASE Ch}π GotoXY( XPos, YPos );π Write( EdLine, ' ' );π GotoXY( XPos+Pos-1, YPos );π END; {IF Kbd.GetKey}π UNTIL Finish;π GetLine := EdLine;π END;ππEND.πππ{ KEYBOARD UNIT }πUNIT Keybd; { Keybd.PAS / Keybd.TPU }ππINTERFACEππUSES Crt, Dos;ππTYPEπ CType = ( UBAR, BLOCK );π Keyboard = OBJECTπ ThisCursor: CType;π PROCEDURE InitKeyBd;π PROCEDURE SetCursor( Cursor: CType );π FUNCTION GetCursor: CType;π FUNCTION GetKbdFlags: Byte;π FUNCTION GetKey( VAR KeyFlags: Byte; VAR FunctKey: Boolean;π VAR Ch: Char ): Boolean;π END;ππ{***************************************************************}π IMPLEMENTATIONπ{***************************************************************}πππ{Keyboard}ππ{-------------------------------------------------π- Name : InitKeyBd -π- Purpose: Set the cursor to underline style -π- and empty keyboard buffer -π-------------------------------------------------}ππPROCEDURE Keyboard.InitKeyBd;π VARπ Ch : Char;π BEGINπ SetCursor( UBAR );π WHILE( KeyPressed ) DO Ch := ReadKey;π END;ππ{-------------------------------------------------π- Name : SetCursor -π- Purpose: Modify number of lines for cursor -π-------------------------------------------------}ππPROCEDURE Keyboard.SetCursor;π VARπ Regs: Registers;π BEGINπ CASE Cursor OFπ UBAR: Regs.Ch := 6;π BLOCK: Regs.Ch := 1;π END;π Regs.CL := 7;π Regs.AH := 1;π Intr( $10, Regs );π END;ππ{-------------------------------------------------π- Name : GetKbdFlags -π- Purpose: Monitor the Insert key -π- Output : Shift key status flag byte -π-------------------------------------------------}ππFUNCTION Keyboard.GetKbdFlags: Byte;π VARπ Regs: Registers;π BEGINπ (* FOR enhanced keyboards: AH := $12 *)π (* FOR normal keyboards: AH := $02 *)π Regs.AH := $12;π Intr( $16, Regs );π IF( Regs.AX AND $80 = $80 ) THEN SetCursor( BLOCK )π ELSE SetCursor( UBAR );π GetKbdFlags := Regs.AX;π END;ππ{-------------------------------------------------π- Name : GetCursor -π- Purpose: Query current cursor state -π-------------------------------------------------}ππFUNCTION Keyboard.GetCursor;π BEGINπ GetCursor := ThisCursor;π END;ππ{-------------------------------------------------π- Name : GetKey -π- Purpose: Get a keypress contents if any -π- Updates a function keypressed flag -π-------------------------------------------------}ππFUNCTION Keyboard.GetKey;π VARπ Result : Boolean;π BEGINπ Result := KeyPressed;π FunctKey := FALSE;π Ch := #$00; {Use this to check for Function key press}π IF Result THEN BEGINπ Ch := ReadKey;π IF( KeyPressed AND ( Ch = #$00 ) ) THEN BEGINπ Ch := ReadKey;π FunctKey := TRUE;π END;π END;π KeyFlags := GetKbdFlags;π GetKey := Result;π END;ππEND.ππ{ DEMO PROGRAM }ππPROGRAM EditDemo;ππ{-------------------------------------------------π- Show off example of global object use -π-------------------------------------------------}ππUSES Crt, EditObj;ππVARπ Editor: LineEdit; {Instantiation of LineEdit OBJECT}π ResultStr: String;πBEGINπ ClrScr;π WITH Editor DOπ BEGINπ InitEdit( 1, 10, 'Edit this sample line');π ResultStr := GetLine;π GotoXY( 1, 15 );π WriteLn( ResultStr );π END;π ReadLn;πEND.π 4 06-22-9309:30ALL BOB GIBSON General Purpos Line Edit IMPORT 46 (****************************************************************)π(* N_EditLn *)π(* *)π(* General Purpose line editor, based on EDITLN by Borland *)π(* Modified for use with multiple lines by *)π(* Bob Gibson of BGShareWare *)π(* *)π(****************************************************************)ππunit N_EditLn;π{$D-,I-,S-}πinterfaceπuses Scrn;ππconstπ NULL = #0;π BS = #8;π LF = #10;π CR = #13;π ESC = #27;π Space = #32;π Tab = ^I;ππ { The following constants are based on the scheme used by the scan keyπ function to convert a two key scan code sequence into one characterπ by adding 128 to the ordinal value of the second character.π }π F1 = #187;π F2 = #188;π F3 = #189;π F4 = #190;π F5 = #191;π F6 = #192;π F7 = #193;π F8 = #194;π F9 = #195;π F10 = #196;π UpKey = #200;π DownKey = #208;π LeftKey = #203;π RightKey = #205;π PgUpKey = #201;π PgDnKey = #209;π HomeKey = #199;π EndKey = #207;π InsKey = #210;π DelKey = #211;π M : Word = 0;πvarπ O, N, R, P : byte;π Ch : Char;π T : String;ππtypeπ CharSet = set of char;ππprocedure EditLine(var S : String;π Len, X, Y : byte;π LegalChars,π Term : CharSet;π var TC : Char );π{ EditLn implements a line editor that supports WordStar commandsπ as well as left-right arrow keys , Home, End, back space, etc.π Paramaters:π S : String to be editedπ Len : Maximum characters allowed to be editedπ X, Y : Starting x an y cordinatesπ LegalChars : Set of characters that will be acceptedπ Term : Set of characters that will cause EditLine to Exitπ (Note LegalChars need not contain Term)π TC : Character that caused EditLn to exitπ}ππfunction ScanKey : char;π{ Reads a key from the keyboard and converts 2 scan code escapeπ sequences into 1 character. }ππimplementationπ{$L keys}πFunction KeyPressed : Boolean ; External;πFunction ReadKey : Char ; External;ππfunction ScanKey : char;π{ Reads a key from the keyboard and converts 2 scan code escapeπ sequences into 1 character. }ππvarπ Ch : Char;πbeginπ Ch := ReadKey;π if (Ch = #0) {and KeyPressed} thenπ beginπ Ch := ReadKey;π if ord(Ch) < 128 thenπ Ch := Chr(Ord(Ch) + 128);π end;π ScanKey := Ch;πend; { ScanKey }ππprocedure EditLine(var S : String;π Len, X, Y : byte;π LegalChars, Term : CharSet;π var TC : Char);π{ EditLn implements a line editor that supports WordStar commandsπ as well as left-right arrow keys , Home, End, back space, etc.π Paramaters:π S : String to be editedπ Len : Maximum characters allowed to be editedπ X, Y : Starting x an y cordinatesπ LegalChars : Set of characters that will be acceptedπ Term : Set of characters that will cause EditLine to Exitπ (Note LegalChars need not contain Term)π TC : Character that caused EditLn to exitπ}π{$V-}ππbeginπ PXY(X,Y);π PWrite(S);π P := Y - 1;π N := Y;π O := X;π Y := 1;π M := 0;π Mem[$40:$17] := (Mem[$40:$17] AND $7F);π repeatπ If ((Mem[$40:$17] AND $80) = $80) Then SetCursor(0,7) Else SetCursor(6,7);π If (Y+P) > 80 Then Beginπ Inc(X);π P := 0;π End;π PXY(X,Y+P);π Ch := ScanKey;π if not (Upcase(Ch) in Term) thenπ case Ch ofπ #32..#126 : if (M < Len) andπ (ch in LegalChars) thenπ beginπ P := succ(P);π M := succ(M);π If ((Mem[$40:$17] AND $80) = $80) Thenπ Delete(S,M,1);π If ((Mem[$40:$17] AND $80) <> $80) Thenπ If Length(S) = Len Then Delete(S,Len,1);π Insert(Ch,S,M);π T := Copy(S,M,Len);π PWrite(T);π endπ Else Writeln(^G);π ^S, LeftKey : if M > 0 then Beginπ If P < 1 Then Beginπ P := 80;π Dec(X);π End;π P := pred(P);π M := pred(M);π End;π ^D, RightKey : if M < Length(S) then Beginπ P := succ(P);π M := succ(M);π End;π HomeKey : Beginπ M := M - P;π P := 0;π End;π EndKey : Beginπ M := M + (79 - P);π P := 79;π If M > Length(S) Then Beginπ P := P - (M - Length(S));π M := Length(S);π End;π End;π UpKey : If X > O Then Beginπ Dec(X);π M := M - 80;π End;π DownKey : If (M+80) < Length(S) Then Beginπ Inc(X);π M := M + 80;π If M > Length(S) Then Beginπ P := P - (M - Length(S));π M := Length(S);π End;π End;π DelKey : if M < Length(S) thenπ beginπ Delete(S,M + 1,1);π T := Copy(S,M+1,Len);π T := T + ' ';π PWrite(T);π end;π BS : if M > 0 thenπ beginπ Delete(S,M,1);π T := Copy(S,M,Len);π If (Y+P-1) < 1 Then Beginπ Dec(X);π P := (81-Y);π PXY(X,P);π Endπ Else PXY(X,Y+P-1);π T := T + ' ';π PWrite(T);π P := pred(P);π M := pred(M);π end;π F9 : Beginπ X := O;π Y := 1;π For R := 1 To Len Do PWrite(' ');π P := 0;π S := '';π M := 0;π End;π else;π end; {of case}π until UpCase(Ch) in Term;π SetCursor(6,7);π PXY(X,Y+P);π M := Length(S);π For R := 1 To (Len-M) Do PWrite('');π TC := Upcase(Ch);πend; { EditLine }ππend.ππUSE XX34 to decode this object code. You MUST Have it to use this unitπAlso, you will need the SCRN.PAS from the SCREEN.SWG packet.πππ*XX3401-000092-070293--68--85-59342--------KEYS.OBJ--1-OF--1πU+M+-2h3KJAuZUQ+++F1HoF3F7U5+0UI++6-+G4E5++++Ed9FJZEIYJHIoJ2++++-p73πEIF9FJY7+++pc-U++E++h+5B3bHug+51JMjgh+TB6MjZLQD6WU6++5E+π***** END OF XX-BLOCK *****πππ 5 08-27-9321:28ALL SEAN PALMER A Simple Input Routine IMPORT 20 3 {πSEAN PALMERππ> name:_______________) problem, how do you make a field where youπ> define the max Chars in the field and doNOT let the person Type moreπ> than that. stop the users keyboard at the last Char in this Case itsπ> 78 Chars max and the field looks like thisππTry this. Send it a default value, the length of the field, and a set ofπChar containing all the valid Characters For the field.ππ}πUses uInput,Crt;ππFunction getName : String;πConstπ nameMax = 20;πVarπ Count : Integer;π attrsave : Byte;πbeginπ GotoXY(12, 2);π Write('ENTER NAME:');π attrsave := TextAttr;π TextColor(0);π TextBackground(7);π GotoXY(26, 2);π for Count := 1 to nameMax doπ Write(' '); {draw inverse field}π GotoXY(26, 2);π getName := input('Nobody', nameMax, ['A'..'Z','a'..'z','.',' ']);π Textattr := attrsave;πend;ππ{----------}ππ{uInput}π{by Sean Palmer}π{released to the public domain}π {2237 Lincoln St.}π {Longmont, CO 80501}π{Alms gladly accepted! 8) }ππUnit uInput;π{$B-,I-,N-,O-,R-,S-,V-,X-}ππInterfaceππ{tCharSet is used to specify Function keys to the input routine}πTypeπ tCharSet = set of Char;ππFunction isKey : Boolean;πInline(π $B4/$B/ {mov ah,$B}π $CD/$21/ {int $21}π $24/$FE); {and al,$FE}ππFunction getKey : Char;πInline(π $B4/7/ {mov ah,7}π $CD/$21); {int $21}ππFunction input(default : String; maxCh : Byte; cs : tCharSet) : String;ππImplementationππFunction input(default : String; maxCh : Byte; cs : tCharSet) : String;πVarπ p : Byte;π c : Char;π s : String[255];πbeginπ s := default;π Repeatπ c := getKey;π if c = #0 thenπ c := Char(Byte(getKey) or $80);π Case c ofπ ^H :π if s[0] <> #0 thenπ beginπ Write(^H, ' ', ^H);π dec(s[0]);π end;π #127 :π beginπ For p := length(s) downto 1 doπ Write(^H, ' ', ^H);π s[0] := #0;π end;π ^M : ; {don't beep}π ' '..'~' :π if length(s) < maxCh thenπ beginπ Write(c);π inc(s[0]);π s[Byte(s[0])] := c;π endπ elseπ Write(^G);ππ elseπ if c in cs thenπ beginπ s[1] := c;π s[0] := #1;π c := ^M;π endπ elseπ Write(^G);π end;π Until (c = ^M) or (c = ^[);ππ if c = ^[ thenπ input := defaultπ elseπ input := s;ππend;ππend.ππ 6 10-28-9311:32ALL RANDALL WOODMAN Generalize Input SWAG9311 40 3 {===========================================================================πDate: 10-02-93 (06:28)πFrom: RANDALL WOODMANπSubj: Inputππ{->>>>GetString<<<<--------------------------------------------}π{ }π{ Filename : GETSTRIN.SRC -- Last Modified 7/14/88 }π{ }π{ This is a generalized string-input procedure. It shows a }π{ field between vertical bar characters at X,Y, with any }π{ string value passed initially in XString left-justified in }π{ the field. The current state of XString when the user }π{ presses Return is returned in XString. The user can press }π{ ESC and leave the passed value of XString undisturbed, even }π{ if XString was altered prior to his pressing ESC. }π{ }π{ From: COMPLETE TURBO PASCAL 5.0 by Jeff Duntemann }π{ Scott, Foresman & Co., Inc. 1988 ISBN 0-673-38355-5 }π{--------------------------------------------------------------}ππPROCEDURE GetString( X,Y : Integer;π VAR XString : String80;π MaxLen : Integer;π Capslock : Boolean;π Numeric : Boolean;π GetReal : Boolean;π VAR RValue : Real;π VAR IValue : Integer;π VAR Error : Integer;π VAR Escape : Boolean);ππVAR I,J : Integer;π Ch : Char;π Cursor : Char;π Dot : Char;π BLength : Byte;π ClearIt : String80;π Worker : String80;π Printables : SET OF Char;π Lowercase : SET OF Char;π Numerics : SET OF Char;π CR : Boolean;πππBEGINπ Printables := [' '..'}']; { Init sets }π Lowercase := ['a'..'z'];π IF GetReal THEN Numerics := ['-','.','0'..'9','E','e']π ELSE Numerics := ['-','0'..'9'];π Cursor := '_'; Dot := '.';π CR := False; Escape := False;π FillChar(ClearIt,SizeOf(ClearIt),'.'); { Fill the clear string }π ClearIt[0] := Chr(MaxLen); { Set clear string to MaxLen }ππ { Convert numbers to string if required: }π IF Numeric THEN { Convert zero values to null string: }π IF (GetReal AND (RValue = 0.0)) ORπ (NOT GetReal AND (IValue = 0)) THEN XString := ''π ELSE { Convert nonzero values to string equiv: }π IF GetReal THEN Str(RValue:MaxLen,XString)π ELSE Str(IValue:MaxLen,XString);ππ { Truncate string value to MaxLen }π IF Length(XString) > MaxLen THEN XString[0] := Chr(MaxLen);π GotoXY(X,Y); Write('|',ClearIt,'|'); { Draw the field }π GotoXY(X+1,Y); Write(XString);π IF Length(XString)<MaxLen THENπ BEGINπ GotoXY(X + Length(XString) + 1,Y);π Write(Cursor) { Draw the Cursor }π END;π Worker := XString; { Fill work string with input string }ππ REPEAT { Until ESC or (CR) entered }π { Wait here for keypress: }π WHILE NOT KeyPressed DO BEGIN {NULL} END;π Ch := ReadKey;ππ IF Ch IN Printables THEN { If Ch is printable... }π IF Length(Worker) >= MaxLen THEN UhUh ELSEπ IF Numeric AND (NOT (Ch IN Numerics)) THEN UhUh ELSEπ BEGINπ IF Ch IN Lowercase THEN IF Capslock THEN Ch := Chr(Ord(Ch)-32);π Worker := CONCAT(Worker,Ch);π GotoXY(X+1,Y); Write(Worker);π IF Length(Worker) < MaxLen THEN Write(Cursor)π ENDπ ELSE { If Ch is NOT printable... }π CASE Ord(Ch) OFπ 8,127 : IF Length(Worker) <= 0 THEN UhUh ELSEπ BEGINπ Delete(Worker,Length(Worker),1);π GotoXY(X+1,Y); Write(Worker,Cursor);π IF Length(Worker) < MaxLen-1 THEN Write(Dot);π END;ππ 13 : CR := True; { Carriage return }ππ 24 : BEGIN { CTRL-X : Blank the field }π GotoXY(X+1,Y); Write(ClearIt);π Worker := ''; { Blank out work string }π END;ππ 27 : Escape := True; { ESC }π ELSE UhUh { CASE ELSE }π END; { CASE }ππ UNTIL CR OR Escape; { Get keypresses until (CR) or }π { ESC pressed }π GotoXY(X + 1,Y); Write(ClearIt);π GotoXY(X + 1,Y); Write(Worker);π IF CR THEN { Don't update XString if ESC hit }π BEGINπ XString := Worker;π IF Numeric THEN { Convert string to Numeric values }π CASE GetReal OFπ True : Val(Worker,RValue,Error);π False : Val(Worker,IValue,Error)π END { CASE }π ELSEπ BEGINπ RValue := 0.0;π IValue := 0π ENDπ ENDπEND; { GETString }π 7 01-27-9412:04ALL JEFF FANJOY Key Input Routine SWAG9402 73 3 > Does anyone know how to make the input line a certain number of linesπ> only!...sya the user only gets to us 3 characters....ππHere is the input routine that I use for all of my programs. You mayπnot need it so precise, so you can cut out anything you don't feel isπnecessary but here goes:π}ππUNIT KeyInput;ππINTERFACEππUSES CRT,CURSOR;ππPROCEDURE GetInput(VAR InStr; {String Passed}π WhatWas: String; {Old value to Remember}π Len: Byte; {Length of String Max=255}π XPosition, {X Cursor Position}π YPosition, {Y Cursor Position}π BackGroundColor, {Background Color}π ForeGroundColor: Integer; {Foreground Color}π BackGroundChar: Char; {Echoed Character on BkSp}π Caps: Boolean); {CAPS?}πIMPLEMENTATIONππPROCEDURE GetInput(VAR InStr;π WhatWas: String;π Len: Byte;π XPosition,π YPosition,π BackGroundColor,π ForeGroundColor: Integer;π BackGroundChar: Char;π Caps: Boolean);ππCONSTπ BkSp: Char = Chr($08);ππVARπ InsertKey: Byte Absolute $0040:$0017;π Temp: String;π Ch2,π C: Char;π A,π U,π B: Byte;π FirstChar,π InsertOn,π NoAdd: Boolean;π NewString: String Absolute InStr;ππBEGINπ InsertKey := InsertKey OR $80; {changes to insert mode}π IF (InsertKey AND $80 > 0) THENπ BEGINπ InsertOn := TRUE;π ShowCursor;π ENDπ ELSEπ BEGINπ InsertOn := FALSE;π BigCursor;π END;π FirstChar := TRUE;π NewString := '';π Temp := '';π GotoXY(XPosition,YPosition);π TextBackGround(BackGroundColor);π TextColor(ForeGroundColor);π FOR U := 1 TO Len DOπ BEGINπ Write(BackGroundChar); {shows how many characters are available}π END;π GotoXY(XPosition,YPosition);π C := Chr($00); {null character input}π TextBackGround(ForeGroundColor);π TextColor(BackGroundColor);π NewString := WhatWas; {starts with previous value in memory}π Write(NewString); {writes previous value to screen for editing}π B := Length(WhatWas);π A := B;π TextBackGround(BackGroundColor);π TextColor(ForeGroundColor);π WHILE (C <> Chr($0D)) AND (C <> Chr($1B)) DO {not CR or ESC}π BEGINπ NoAdd := FALSE;π IF Caps THEN C := UpCase(ReadKey) {if Caps read uppercase else...}π ELSE C := ReadKey;π CASE C OFπ Chr($08): IF B >= 1 THEN {backspace}π BEGINπ IF FirstChar THENπ BEGINπ FirstChar := FALSE;π GotoXY(XPosition,YPosition);π Write(NewString);π END;π Delete(NewString,B,1);π Write(BkSp,BackGroundChar,BkSp);π Dec(B);π GotoXY(XPosition+B,WhereY);π FOR U := B TO Length(NewString) DOπ BEGINπ IF B <> U THEN Temp := Temp + NewString[U]π ELSE Temp := '';π END;π Write(Temp);π FOR U := Length(NewString)+1 TO Len DOπ BEGINπ Write(BackGroundChar);π END;π GotoXY(XPosition+B,WhereY);π NoAdd := TRUE;π Dec(A);π END;π Chr($1B): BEGIN {Escape}π NoAdd := TRUE;π NewString := WhatWas;π END;π Chr($19): BEGIN {^Y = clear the editing line}π NoAdd := TRUE;π NewString := '';π GotoXY(XPosition,YPosition);π FOR U := 1 TO Len DOπ BEGINπ Write(BackGroundChar);π END;π FirstChar := FALSE;π GotoXY(XPosition,YPosition);π B := 0;π A := 0;π END;π Chr($0D): NoAdd := TRUE; {enter <CR>}π Chr($00): BEGIN {extended keys always start with null character}π NoAdd := TRUE;π IF FirstChar THENπ BEGINπ FirstChar := FALSE;π GotoXY(XPosition,YPosition);π Write(NewString);π END;π C := UpCase(ReadKey);π CASE C OFπ Chr(77): BEGIN {right arrow}π IF B <= Length(NewString)-1 THENπ BEGINπ GotoXY(XPosition+B+1,WhereY);π Inc(B);π END;π END;π Chr(75): BEGIN {left arrow}π IF B >= 1 THENπ BEGINπ GotoXY(XPosition+B-1,WhereY);π Dec(B);π END;π END;π Chr(71): BEGIN {home}π GotoXY(XPosition,YPosition);π B := 0;π END;π Chr(79): BEGIN {end}π GotoXY(XPosition+Length(NewString),YPosition);π B := Length(NewString);π END;π Chr(82): BEGIN {insert}π IF InsertOn THENπ BEGINπ InsertOn := FALSE;π BigCursor;π ENDπ ELSEπ BEGINπ InsertOn := TRUE;π ShowCursor;π END;π END;π Chr(83): BEGIN {del}π IF (B < Length(NewString)) AND (B >= 0) THENπ BEGINπ Delete(NewString,B+1,1);π FOR U := B TO Length(NewString) DOπ BEGINπ IF U <> B THEN Temp := Temp + NewString[U]π ELSE Temp := '';π END;π GotoXY(XPosition+B,WhereY);π Write(Temp);π Write(BackGroundChar);π GotoXY(XPosition+B,WhereY);π Dec(A);π END;π END;π END;π WHILE Keypressed DO C := ReadKey;π END;π END;π IF ((A < Len) AND (NoAdd = FALSE) AND (C <> Chr($08))) OR ((FirstChar) ANDπ (NOT(NoAdd)) AND (C <> Chr($08))) THENπ BEGINπ IF FirstChar THEN {if first character typed is a real character,thenπ string is removed to start new one else...}π BEGINπ Delete(NewString,1,Length(NewString));π GotoXY(XPosition,YPosition);π B := 0;π A := 0;π FOR U := 1 TO Len DOπ BEGINπ Write(BackGroundChar);π END;π GotoXY(XPosition,YPosition);π FirstChar := FALSE;π END;π Inc(B);π Inc(A);π IF InsertOn THENπ BEGINπ Insert(C,NewString,B);π FOR U := B TO Length(NewString) DOπ BEGINπ IF B <> U THEN Temp := Temp + NewString[U]π ELSE Temp := '';π END;π GotoXY(XPosition+B-1,WhereY);π Write(C);π Write(Temp);π GotoXY(XPosition+B,WhereY);π ENDπ ELSEπ BEGINπ Insert(C,NewString,B);π Delete(NewString,B+1,1);π Write(C)π END;π END;π END;π TextBackGround(0);πEND;πππBEGINπEND.ππ 8 01-27-9412:13ALL BERNIE PALLEK Masked Input SWAG9402 22 3 {π> The text on the screen would be something like:π> What is your phone number? ( ) -π> ^^^ ^^^ ^^^^π> But text could only be entered at the marked locations. As soon as oneπ> section is full it would move to the one beside it but read in a differentπ> variable..ππHow about this: (it's tested, BTW)π}ππUSES Crt;ππVARπ ts : String;ππPROCEDURE MaskedReadLn(VAR s : String; mask : String; fillCh : Char);π{ in 'mask', chars with A will only accept alpha input, and charsπ with 0 will only accept numeric input; spaces accept anything }πVAR ch : Char; sx, ox, oy : Byte;πBEGINπ s := ''; ox := WhereX; oy := WhereY; sx := 0;π REPEATπ Inc(sx);π IF (mask[sx] IN ['0', 'A']) THENπ Write(fillCh)π ELSE IF (mask[sx] = '_') THENπ Write(' ')π ELSE Write(mask[sx]);π UNTIL (sx = Length(mask));π sx := 0;π WHILE (NOT (mask[sx + 1] IN [#32, '0', 'A']))π AND (sx < Length(mask)) DO BEGINπ Inc(sx);π s := s + mask[sx];π END;π GotoXY(ox + sx, oy);π REPEATπ ch := ReadKey;π IF (ch = #8) THEN BEGINπ IF (Length(s) > sx) THEN BEGINπ IF NOT (mask[Length(s)] IN [#32, '0', 'A']) THEN BEGINπ REPEATπ s[0] := Chr(Length(s) - 1);π GotoXY(WhereX - 1, WhereY);π UNTIL (Length(s) <= sx) OR (mask[Length(s)] IN [#32, '0', 'A']);π END;π s[0] := Chr(Length(s) - 1); GotoXY(WhereX - 1, WhereY);π Write(fillCh); GotoXY(WhereX - 1, WhereY);π END ELSE BEGINπ Sound(440);π Delay(50);π NoSound;π END;π END ELSE IF (Length(s) < Length(mask)) THEN BEGINπ CASE mask[Length(s) + 1] OFπ '0' : IF (ch IN ['0'..'9']) THEN BEGINπ Write(ch);π s := s + ch;π END;π 'A' : IF (UpCase(ch) IN ['A'..'Z']) THEN BEGINπ Write(ch);π s := s + ch;π END;π #32 : BEGINπ Write(ch);π s := s + ch;π END;π END;π WHILE (Length(s) < Length(mask))π AND (NOT (mask[Length(s) + 1] IN [#32, '0', 'A'])) DO BEGINπ IF (mask[Length(s) + 1] = '_') THEN s := s + ' ' ELSEπ s := s + mask[Length(s) + 1];π GotoXY(WhereX + 1, WhereY);π END;π END;π UNTIL (ch IN [#13, #27]);πEND;ππBEGINπ ClrScr;π Write('Enter phone number: ');π MaskedReadLn(ts, '(000)_000-0000', '_');π WriteLn;π Write('Enter postal code: ');π MaskedReadLn(ts, 'A0A_0A0', '_');π WriteLn;πEND.ππ{πIt can be improved with colours and such stuff, but it may suit yourπneeds without enhancement. If you have questions about how this works,πfeel free to ask.π}ππ 9 02-03-9409:58ALL LOU DUCHEZ DATABOX.PAS SWAG9402 121 3 unit databox;ππ{ This is a unit to let you open data-entry boxes on the screen for quick 'n'π easy data entry. It operates on variables of type "string", "integer",π "word", "byte", "longint" and "boolean". There are two main routines toπ call here:ππ OpenBox(x, y, data, temp, type) -- to open a data entry box on the screenπ ReadBoxes -- to read all data entry boxesππ The parameters for "OpenBox":π x, y -- the coordinates where the box should appear on the screenπ data -- the variable you want to do data entry onπ type -- an character indicating what type of variable you're working on.π Valid "types" are:ππ 'S' -- String 'I' -- Integerπ 'W' -- Word 'L' -- LongIntπ 'Y' -- Byte 'B' -- Booleanππ temp -- a string "template" indicating the size of the data entryπ field and the data acceptable at each position. The followingπ characters mean the following:ππ 'X' -- accept any character ( strings )π '!' -- accept any character, but capitalize ( strings )π '9' -- accept only digits and minus signs ( numeric )π 'T' -- accept only 'T' and 'F' ( boolean )π 'Y' -- accept only 'T', 'F', 'Y' and 'N' ( boolean )ππ All of these template characters are valid on strings. Forπ numeric fields, the whole template gets converted to all 9's;π for boolean, the template will either be a single 'T' or 'Y'π (it defaults to 'T').ππ Examples:ππ OpenBox(12, 10, counter, '99999', 'I');ππ -- is for an integer variable "counter". It opens a data entry box atπ position (12, 10), and is five characters across.ππ OpenBox(1, 14, yes_or_no, 'Y', 'b')ππ -- opens a data entry box for a boolean variable "yes_or_no", and willπ accept only a "Y" or an "N" as input.ππ OpenBox(1, 25, namestring, '!XXXXXXXXXXXXXXXX', 's')ππ -- opens a data entry box for a string variable "namestring"; it willπ automatically capitalize the first letter, and accept every otherπ character entered "as is".ππ When you have opened all your data boxes, call "ReadBoxes" to allowπ the user to actually input into the boxes. Once you are done, theπ boxes "close" so you can't do any more data entry on them. There isπ also a "ClearBoxes" procedure to manually "close" open boxes, and aπ "Qwrite" procedure for doing direct video writes.ππ Oh, I'm Lou Duchez, and if you could leave my name somewhere in theπ code I'd appreciate it. I'll never be rich off of public domain codeπ like this, so at least help me get famous ...π }π{π-------------------------------------------------------π}πinterfaceππconst boxforeground: byte = 1;π boxbackground: byte = 7;ππprocedure qwrite(x, y: byte; s: string; f, b: byte);πprocedure openbox(x, y: byte; var data; template: string; datatype: char);πprocedure clearboxes;πprocedure readboxes;π{π-------------------------------------------------------π}πimplementationπuses crt; { for "checkbreak" and "readkey" functions }ππconst maxboxes = 255; { open up to 255 data boxes simultaneously }ππtype boxrecord = record { holds all the data we need }π x, y: byte; { position to display on screen }π template: string; { describes size and type of data field }π dataptr: pointer; { points to data }π datatype: char; { type of data we're pointing to }π end;ππvar boxes: array[1 .. maxboxes] of ^boxrecord; { all the data boxes }π boxcount, thisbox, boxpos, boxlength: byte;π boxstring: string;π boxmodified: boolean;π{π-------------------------------------------------------π}πprocedure qwrite(x, y: byte; s: string; f, b: byte); { direct video writes }ππ{ x, y: coordinates to display string at }π{ s: the string to display }π{ f, b: the foreground and background colors to display in }ππtype videolocation = record { video memory locations }π videodata: char; { character displayed }π videoattribute: byte; { attributes }π end;ππvar cnter: byte;π videosegment: word;π vidptr: ^videolocation;π videomode: byte absolute $0040:$0049;π scrncols: byte absolute $0040:$004a;π monosystem: boolean;πbeginππ{ Find the memory location where the string will be displayed at, according toπ the monitor type and screen location. Then associate the pointer VIDPTR withπ that memory location: VIDPTR is a pointer to type VIDEOLOCATION. Insert theπ screen data and attribute; now go to the next character and video location. }ππ monosystem := (videomode = 7);π if monosystem then videosegment := $b000 else videosegment := $b800;π vidptr := ptr(videosegment, 2*(scrncols*(y - 1) + (x - 1)));π for cnter := 1 to length(s) do beginπ vidptr^.videoattribute := (b shl 4) + f;π vidptr^.videodata := s[cnter];π inc(vidptr);π end;π end;π{π-------------------------------------------------------π}πprocedure movecursor(boxnum, position: byte); { Positions cursor. }πvar tmpx, tmpy: byte;πbeginπ tmpx := (boxes[boxnum]^.x - 1) + (position - 1);π tmpy := (boxes[boxnum]^.y - 1);π asmπ mov ah, 02h { Move cursor here. I don't use GOTOXY because it }π mov bh, 00h { is window-dependent. }π mov dh, tmpyπ mov dl, tmpxπ int 10hπ end;π end;π{π-------------------------------------------------------π}πprocedure openbox(x, y: byte; var data; template: string; datatype: char);πvar i: byte;π datastring, tempstring: ^string;πbeginπ if boxcount < maxboxes then begin { If we have room for another data }π inc(boxcount); { box, allocate memory for it from }π new(boxes[boxcount]); { the heap and fill its fields. }π boxes[boxcount]^.x := x;π boxes[boxcount]^.y := y;π boxes[boxcount]^.dataptr := @data;π boxes[boxcount]^.template := template;π boxes[boxcount]^.datatype := upcase(datatype);π case upcase(datatype) ofππ { "Fix" data entry template as needed. Make sure the string data andπ the template are of the same length. Numeric templates should consistπ of all 9's. Boolean templates should be either 'Y' or 'T'. }ππ 'S': beginπ datastring := boxes[boxcount]^.dataptr;π tempstring := addr(boxes[boxcount]^.template);π while length(datastring^) < length(tempstring^) doπ datastring^ := datastring^ + ' ';π while length(tempstring^) < length(datastring^) doπ tempstring^ := tempstring^ + ' ';π end;π 'W', 'I', 'L', 'Y': for i := 1 to length(template) doπ boxes[boxcount]^.template[i] := '9';π 'B': beginπ boxes[boxcount]^.template[0] := #1;π if not (boxes[boxcount]^.template[1] in ['Y', 'T']) thenπ boxes[boxcount]^.template := 'T';π end;π end;π end;π end;π{π-------------------------------------------------------π}πprocedure clearboxes; { Free up all memory for "box" data. }πbeginπ while boxcount > 0 do beginπ dispose(boxes[boxcount]);π dec(boxcount);π end;π end;π{π-------------------------------------------------------π}πprocedure fixstring(boxnumber: byte); { Adjusts string for displaying }πvar i: byte; { so that each character adheres to }πbegin { the corresponding template char. }π for i := 1 to length(boxstring) doπ case upcase(boxes[boxnumber]^.template[i]) ofπ 'X': ;π '!': boxstring[i] := upcase(boxstring[i]);π '9': if not (boxstring[i] in ['-', '0' .. '9']) then boxstring[i] := ' ';π 'T': case upcase(boxstring[i]) ofπ 'Y', 'T': boxstring[i] := 'T';π 'N', 'F': boxstring[i] := 'F';π else boxstring[i] := ' ';π end;π 'Y': case upcase(boxstring[i]) ofπ 'Y', 'T': boxstring[i] := 'Y';π 'N', 'F': boxstring[i] := 'N';π else boxstring[i] := ' ';π end;π end;π qwrite(boxes[boxnumber]^.x, boxes[boxnumber]^.y, boxstring,π boxforeground, boxbackground);π end;π{π-------------------------------------------------------π}πprocedure displaybox(boxnumber: byte); { Convert data to string and display. }πvar lentemplate: byte;π pntr: pointer;πbeginπ pntr := boxes[boxnumber]^.dataptr;π lentemplate := length(boxes[boxnumber]^.template);π case boxes[boxnumber]^.datatype ofπ 'S': boxstring := string(pntr^);π 'I': str(integer(pntr^): lentemplate, boxstring);π 'W': str(word(pntr^): lentemplate, boxstring);π 'Y': str(byte(pntr^): lentemplate, boxstring);π 'L': str(longint(pntr^): lentemplate, boxstring);π 'B': if boolean(pntr^) then boxstring := 'T' else boxstring := 'F';π end;π fixstring(boxnumber);π end;π{π-------------------------------------------------------π}πprocedure deletekey; { delete: remove character at cursor and shift over }πvar i: byte;πbeginπ boxmodified := true;π for i := boxpos to boxlength - 1 do boxstring[i] := boxstring[i + 1];π boxstring[boxlength] := ' ';π end;ππprocedure backspace; { backspace: back up one and delete if we're }πbegin { still in the same box }π boxpos := boxpos - 1;π if boxpos = 0 then beginπ dec(thisbox);π boxpos := 255;π endπ else deletekey;π end;ππ{ Enter, Tab, and Shift-Tab move you to the beginning of prev/next box }ππprocedure enterkey; begin inc(thisbox); boxpos := 1; end;πprocedure tab; begin inc(thisbox); boxpos := 1; end;πprocedure reversetab; begin dec(thisbox); boxpos := 1; end;ππ{ PgUp, PgDn, Esc take you out of editing; "Esc" indicates that theπ "current" box should not be updated }ππprocedure pageup; begin thisbox := 0; end;πprocedure pagedown; begin thisbox := 0; end;πprocedure esckey; begin thisbox := 0; boxmodified := false; end;ππ{ Up / Down }ππprocedure moveup; begin dec(thisbox); end;πprocedure movedown; begin inc(thisbox); end;ππprocedure moveleft; { Move left; if we go too far left, move up }πbeginπ dec(boxpos);π if (boxpos = 0) then beginπ boxpos := 255;π moveup;π end;π end;ππprocedure moveright; { Move right; if we go too far right, move down }πbeginπ inc(boxpos);π if (boxpos > boxlength) then beginπ boxpos := 1;π movedown;π end;π end;ππprocedure literalkey(keyin: char); { accept character into field }πvar i: byte;π goodkey, insmode: boolean;π keyboardstat: byte absolute $0040:$0017;πbeginπ case upcase(boxes[thisbox]^.template[boxpos]) of { does char match tmplt? }π '9': goodkey := (keyin in ['-', '0'..'9']);π 'T': goodkey := (upcase(keyin) in ['T', 'F']);π 'Y': goodkey := (upcase(keyin) in ['T', 'F', 'Y', 'N']);π else goodkey := true;π end;π if goodkey then begin { character matches template -- use it }π boxmodified := true;π insmode := (keyboardstat and $80 = $80);π if insmode then beginπ i := length(boxstring); { "Insert" mode: make space for new char }π while i > boxpos do beginπ boxstring[i] := boxstring[i - 1];π dec(i);π end;π end;π boxstring[boxpos] := keyin; { enter character and move to the right }π moveright;π end;π end;π{π-------------------------------------------------------π}πprocedure readbox; { get data input on the box specified by THISBOX }πvar keyin: char;π startingbox, i: byte;π pntr: pointer;π dummyint: integer;π numstring: string;πbeginπ boxmodified := false; { "housekeeping" here }π startingbox := thisbox;π displaybox(thisbox);π boxlength := length(boxstring);π if boxpos > boxlength then boxpos := boxlength; { cursor positioning }π if boxpos < 1 then boxpos := 1;π while (thisbox = startingbox) andπ (boxpos >= 1) and (boxpos <= boxlength) do begin { process field }π fixstring(startingbox);π movecursor(startingbox, boxpos);π keyin := readkey; { Interpret keystrokes here }π case keyin ofπ #0: case readkey ofπ #15: reversetab;π #72: moveup;π #73: pageup;π #75: moveleft;π #77: moveright;π #80: movedown;π #81: pagedown;π #83: deletekey;π end;π #8: backspace;π #9: tab;π #13: enterkey;π #27: esckey;π else literalkey(keyin);π end;π end;π if boxmodified then begin { If data was changed, update variable }ππ { This section handles numeric decoding. Since "Val" gets real uppityπ if there are spaces in the middle of your string, these couple loopsπ isolates the first section of the data entry string surrounded byπ spaces. Then "Val" processes that part. }ππ i := 1;π while (i <= length(boxstring)) and (boxstring[i] = ' ') do inc(i);π numstring[0] := #0;π while (i <= length(boxstring)) and (boxstring[i] <> ' ') do beginπ inc(numstring[0]);π numstring[length(numstring)] := boxstring[i];π inc(i);π end;π pntr := boxes[startingbox]^.dataptr;ππ { Put the updated data back into its original variable. }ππ case boxes[startingbox]^.datatype ofπ 'S': string(pntr^) := boxstring;π 'I': val(numstring, integer(pntr^), dummyint);π 'W': val(numstring, word(pntr^), dummyint);π 'Y': val(numstring, byte(pntr^), dummyint);π 'L': val(numstring, longint(pntr^), dummyint);π 'B': boolean(pntr^) := (upcase(boxstring[1]) = 'Y') orπ (upcase(boxstring[1]) = 'T');π end;π end;ππ { Do a final data display. }ππ displaybox(startingbox);π movecursor(startingbox, boxlength + 1);π end;π{π-------------------------------------------------------π}πprocedure readboxes; { gets data input on all boxes }πvar oldcheckbreak: boolean;πbeginπ oldcheckbreak := checkbreak;π checkbreak := false;π for thisbox := 1 to boxcount do displaybox(thisbox); { display data boxes }π thisbox := 1;π boxpos := 1;π while (thisbox >= 1) and (thisbox <= boxcount) do readbox;π clearboxes;π checkbreak := oldcheckbreak;π end;π{π-------------------------------------------------------π}πbegin { initialize to "no boxes" }π boxcount := 0;π end.ππ==============================================================================πTEST PROGRAM:π==============================================================================πprogram datatest;πuses databox, crt;ππvar i: integer; s: string; w: word;π b: boolean; l: longint; y: byte;ππbeginπ clrscr;π i := 10; openbox(1, 1, i, '999999', 'i');π w := 10; openbox(1, 3, w, '999999', 'w');π s := 'SpamBurger'; openbox(1, 5, s, '!xxxxxxxxxxxxxxx', 's');π readboxes;π gotoxy(1, 18); writeln(i); writeln(w); writeln(s);ππ b := false; openbox(1, 7, b, 'Y', 'b');π l := 10; openbox(1, 9, l, '9999999999', 'l');π y := 20; openbox(1,11, y, '9999999999', 'y');π readboxes;π gotoxy(1, 21); writeln(b); writeln(l); writeln(y);π end.π