home *** CD-ROM | disk | FTP | other *** search
- unit keyboard;
-
- (*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*)
- (* *)
- (* Turbo Pascal E-Z keyboard interface unit; contains a greatly enhanced *)
- (* readkey function (getkey), error-free numeric input routines for *)
- (* inputting signed and unsigned integers and real numbers (readint, *)
- (* readno, and readreal), string input procedures with line editing and *)
- (* and the ability to limit input width (readstr and editstr), and many *)
- (* handy miscellaneous routines. Does not use the CRT unit; requires a *)
- (* compatible BIOS. *)
- (* *)
- (* Author: Tom Swingle *)
- (* *)
- (* Author can be contacted via e-mail at: *)
- (* tswingle@oucsace.cs.ohiou.edu -or- swingle@duce.cs.ohiou.edu *)
- (* *)
- (* or via regular U.S. mail: *)
- (* Tom Swingle *)
- (* 114 Grosvenor St. (campus address) *)
- (* Athens, OH 45701 *)
- (* *)
- (* Tom Swingle *)
- (* Rt. 1 Box 292 (After June, 1992) *)
- (* Waterford, OH 45786 *)
- (* *)
- (* All code herein (except modifications made as noted) is the property *)
- (* of the author, Copyright 1991. If this code is modified, all *)
- (* modifications must be documented by the modifier before the code is *)
- (* distributed. This file is not to be distributed if any portion of *)
- (* this comment block has been removed. However, modifiers may add *)
- (* modification comments into this comment block so long as all of the *)
- (* additions are made after all other text in the block, and no text is *)
- (* removed. All documentation and demonstration programs that came with *)
- (* this file should be redistributed along with this file. *)
- (* *)
- (*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*)
-
- interface
-
- {$DEFINE NOCRT}
-
- { Remove the above line if you are using the CRT unit and do not want the
- last four routines defined in the interface section to interfere with the
- routines normally defined in the CRT unit. }
-
- const
- alt=132; { Alt + letter will return the character 132 above the letter }
- home=#128; uparrow=#129; pgup=#130; { numeric }
- leftarrow=#131; rightarrow=#132; { keypad }
- end_=#133; downarrow=#134; pgdn=#135; { keys }
- ins=#136; del=#137;
- F1=#138; F2=#139; F3=#140; F4=#141; F5=#142;
- F6=#143; F7=#144; F8=#145; F9=#146; F10=#147;
- shiftF1=#148; shiftF2=#149; shiftF3=#150; shiftF4=#151; shiftF5=#152;
- shiftF6=#153; shiftF7=#154; shiftF8=#155; shiftF9=#156; shiftF10=#157;
- cntlF1=#158; cntlF2=#159; cntlF3=#160; cntlF4=#161; cntlF5=#162;
- cntlF6=#163; cntlF7=#164; cntlF8=#165; cntlF9=#166; cntlF10=#167;
- altF1=#168; altF2=#169; altF3=#170; altF4=#171; altF5=#172;
- altF6=#173; altF7=#174; altF8=#175; altF9=#176; altF10=#177;
- { Regular, shifted, control, and alternate sets of function keys }
- cntlhome=#183; cntlpgup=#178;
- cntlleftarrow=#179; cntlrightarrow=#180;
- cntlend=#181; cntlpgdn=#182; { Control + keypad keys }
- alt1=#184; alt2=#185; alt3=#186; alt4=#187; alt5=#188;
- alt6=#189; alt7=#190; alt8=#191; alt9=#192; alt0=#193;
- { Alt + numbers from top row of keyboard }
- altminus=#194; altequal=#195; { Alt + "-" or "=" from middle of keyboard }
- reversetab=#196; { Shift + tab key }
- on=true; { Boolean constans for GetCapslock, GetNumLock, }
- off=false; { GetScrollLock, SetCapsLock, SetNumLock, and SetScrollLock }
- nonnumeric:boolean=false; { Disallow numbers on numeric keypad }
-
- type charset=set of char;
-
- var alttyped:boolean; { TRUE if the last key returned by getkey was entered
- on the numeric keypad. This can be done by holding down the alt key and
- typing the key's ASCII code on the numeric keypad. Undefined before the
- first call to getkey. }
-
- function getkey:char; { enhanced readkey }
- procedure readno(var number:word; lobound,hibound:word);
- procedure readint(var number:integer; lobound,hibound:integer);
- procedure readreal(var number:real; lobound,hibound:real; decimals:byte);
- { Read an unsigned integer, signed integer, or real number between lobound
- and hibound, and with maximum number of decimal places for real number. }
- procedure readstr(var s:string; maxlen:byte; charstoexclude:charset);
- { Read a new string into s, starting with an empty string; allow no more
- than maxlen chars; do not allow any characters in the charstoexclude set
- to be entered into the string. }
- procedure editstr(var s:string; maxlen:byte; charstoexclude:charset);
- { Edit the string currently in s; same rules as readstr. }
- procedure flushbuffer; { Flush all typed-ahead keystrokes from buffer. }
- procedure setcapslock(state:boolean); { Set the caps lock, num lock, }
- procedure setnumlock(state:boolean); { scroll lock, or insert key state }
- procedure setscrolllock(state:boolean); { on or off. State=TRUE means turn }
- procedure setinsert(state:boolean); { on; state=FALSE means turn off. }
- function getcapslock:boolean; { \ }
- function getnumlock:boolean; { \Return current caps lock, num lock, }
- function getscrolllock:boolean; { /scroll lock, or insert state. }
- function getinsert:boolean; { / }
- function screenwidth:byte; { Tell how many characters wide the screen is. }
- function leftshiftdown:boolean; { Returns true if left shift key is down. }
- function rightshiftdown:boolean; { Returns true if right shift key is down. }
- function shiftdown:boolean; { Returns true if either shift key is down. }
- function controldown:boolean; { Returns true if control key is down. }
- function altdown:boolean; { Returns true if alt key is down. }
- procedure chgcursor(startline,endline:byte);
- { Change the cursor so it starts at startline and ends at endline. }
- { Chgcursor ($20,0) will completely erase the cursor. }
- procedure getcursor(var startline,endline:byte);
- { Get the current starting and ending line of the cursor. }
- {$IFDEF NOCRT}
- function keypressed:boolean; { Returns true if a key is waiting in buffer. }
- function wherex:byte; { Returns x-coordinate of cursor. }
- function wherey:byte; { Returns y-coordinate of cursor. }
- procedure gotoxy(x,y:byte); { Positions cursor at (x,y). }
- {$ENDIF}
-
- implementation
-
- uses dos;
-
- var
- keyflag:byte absolute $40:$17; { Location of keyboard status flags. }
- scancode:byte; { Contains the scan code of last key pressed. }
-
- { Following are five routines normally defined in the CRT unit. Originally,
- this unit was written using these routines directly from the CRT unit.
- However, they have been rewritten using BIOS calls because the CRT unit
- seems to be incompatible with text modes greater than 80 columns wide.
- Four of them are included in the interface section so that programs using
- this unit need not include the CRT unit in order to do basic keyboard
- functions. A program using the CRT unit can call crt.keypressed,
- crt.wherex, etc., if use of the CRT unit's routines is desired (or simply
- remove the conditional compilation definition of NOCRT above. This is
- probably unecessary because the routines are functionally equivalent, to
- the best of my knowledge, except for one difference with keypressed.
- Please read KEYBOARD.DOC for more details. }
-
- function wherex:byte;
-
- var regs:registers;
-
- begin
- regs.ah:=$F;
- intr($10,regs); { Get correct display page into bh }
- regs.ah:=3;
- intr($10,regs); { Call BIOS int 10h, function 3--get cursor position }
- wherex:=regs.dl+1;
- end;
-
- function wherey:byte;
-
- var regs:registers;
-
- begin
- regs.ah:=$F;
- intr($10,regs); { Get correct display page into bh }
- regs.ah:=3;
- intr($10,regs); { Call BIOS int 10h, function 3--get cursor position }
- wherey:=regs.dh+1;
- end;
-
- procedure gotoxy(x,y:byte);
-
- var regs:registers;
-
- begin
- regs.ah:=$F;
- intr($10,regs); { Get correct display page into bh }
- regs.ah:=2;
- regs.dl:=x-1;
- regs.dh:=y-1;
- intr($10,regs); { Call BIOS int 10h, function 2--set cursor position }
- end;
-
- function keypressed:boolean;
-
- { Please read KEYBOARD.DOC for information on the additional side effect
- that this function has. }
-
- var regs:registers;
-
- begin
- repeat
- regs.ah:=1;
- intr($16,regs); { Call BIOS int 16h, function 1--check buffer status }
- if (regs.flags and fzero=0) and (regs.ah=76) and nonnumeric
- then begin { clear out keypad 5's in non-numeric mode }
- regs.ah:=0;
- intr($16,regs); { Call BIOS int 16h, function 0--get keystroke }
- end;
- until (regs.flags and fzero<>0) or (regs.flags and fzero=0) and
- ((regs.ah<>76) or not nonnumeric);
- keypressed:=regs.flags and fzero=0; { ZF clear if keystroke waiting }
- end;
-
- function readkey:char;
-
- var regs:registers;
-
- begin
- regs.ah:=0;
- intr($16,regs); { Call BIOS int 16h, function 0--get keystroke }
- readkey:=chr(regs.al);
- scancode:=regs.ah; { global variable containing scan code of last key }
- end;
-
- procedure beep;
-
- begin
- { Not implemented. Adding a beep without the CRT unit would require
- appropriate Port out instructions, as well as a calibrated delay loop,
- and the usefulness of a beep as a signal to the user is questionable, and
- somewhat a matter of taste. If you care to add a beep to signal
- incorrect input, put it here (remove this comment if you do). }
- end;
-
- function screenwidth;
-
- var regs:registers;
-
- begin
- regs.ah:=$F;
- intr($10,regs); { Call BIOS int 10h, function 15--get video mode }
- screenwidth:=regs.ah;
- end;
-
- procedure backup(count:byte);
-
- { Back up the cursor a given number of spaces, allowing for backing up in
- the leftmost column of the screen, which takes it to the row above }
-
- var x,y:integer;
-
- begin
- x:=wherex; y:=wherey;
- dec(x,count); { Back up the appropriate number of spaces }
- while x<1 do begin { If it goes off the left edge, move to the row above }
- inc(x,screenwidth);
- dec(y);
- end;
- gotoxy(x,y);
- end;
-
- function getkey;
-
- var
- head:byte;
- ch:char;
-
- begin
- repeat
- ch:=readkey;
- alttyped:=scancode=0;
- { A character typed on the numeric keypad will have a scan code of 0 }
- if nonnumeric and (ch in ['0'..'9','.']) and (scancode>70) then begin
- case ch of { Translate from number key to cursor control key }
- '0':getkey:=ins;
- '1':getkey:=end_;
- '2':getkey:=downarrow;
- '3':getkey:=pgdn;
- '4':getkey:=leftarrow;
- '6':getkey:=rightarrow;
- '7':getkey:=home;
- '8':getkey:=uparrow;
- '9':getkey:=pgup;
- '.':getkey:=del;
- end;
- if ch<>'5' then exit;
- end;
- until not((ch='5') and nonnumeric and (scancode>70));
- if ch=#0 then begin { Special keys return an ASCII code=0. Process them. }
- ch:=chr(scancode);
- case ch of
- #3: getkey:=#0; { null }
- #15: getkey:=reversetab; { shift + tab key }
- #59..#68: getkey:=chr(ord(ch)+79); { F1..F10 }
- #84..#113: getkey:=chr(ord(ch)+64); { any other F key }
- #71..#73: getkey:=chr(ord(ch)+57); { home, up arrow, pgup }
- #75: getkey:=leftarrow;
- #77: getkey:=rightarrow;
- #79..#83: getkey:=chr(ord(ch)+54); { end, down arrow, pgdn, ins, del }
- #115..#131:getkey:=chr(ord(ch)+64); { control+left arrow, right arrow,
- end, pgdn, home; alt+1,2,...,9,0,_,= }
- #132: getkey:=cntlpgup;
- #16: getkey:=chr(alt+ord('Q'));
- #17: getkey:=chr(alt+ord('W'));
- #18: getkey:=chr(alt+ord('E'));
- #19: getkey:=chr(alt+ord('R'));
- #20: getkey:=chr(alt+ord('T'));
- #21: getkey:=chr(alt+ord('Y'));
- #22: getkey:=chr(alt+ord('U'));
- #23: getkey:=chr(alt+ord('I'));
- #24: getkey:=chr(alt+ord('O'));
- #25: getkey:=chr(alt+ord('P'));
- #30: getkey:=chr(alt+ord('A'));
- #31: getkey:=chr(alt+ord('S'));
- #32: getkey:=chr(alt+ord('D'));
- #33: getkey:=chr(alt+ord('F'));
- #34: getkey:=chr(alt+ord('G'));
- #35: getkey:=chr(alt+ord('H'));
- #36: getkey:=chr(alt+ord('J'));
- #37: getkey:=chr(alt+ord('K'));
- #38: getkey:=chr(alt+ord('L'));
- #44: getkey:=chr(alt+ord('Z'));
- #45: getkey:=chr(alt+ord('X'));
- #46: getkey:=chr(alt+ord('C'));
- #47: getkey:=chr(alt+ord('V'));
- #48: getkey:=chr(alt+ord('B'));
- #49: getkey:=chr(alt+ord('N'));
- #50: getkey:=chr(alt+ord('M'));
- end;
- end else getkey:=ch; { If not #0, return ch as is }
- end;
-
- procedure readno;
-
- var
- i,maxlen:byte;
- temp:longint;
- ch:char;
- s:string[5];
- error:integer;
-
- begin
- if hibound<lobound then exit;
- str(hibound,s);
- maxlen:=length(s); { Figure maximum input width that can be needed }
- repeat
- s:=''; { Set s to null }
- repeat { Get characters into s until ^M is pressed }
- ch:=getkey;
- case ch of
- '0'..'9' : if length(s)<maxlen then begin
- s:=s+ch;
- write(ch)
- end;
- #8 : if length(s)>0 then begin
- delete(s,length(s),1);
- backup(1);
- write(' ');
- backup(1);
- end;
- #13 : if length(s)=0 then exit; { null string; no changes }
- end
- until ch=#13;
- val(s,temp,error); { Now test number entered against bounds passed }
- if (temp<lobound) or (temp>hibound) then begin
- beep;
- backup(length(s));
- for i:=1 to length(s) do write(' ');
- backup(length(s));
- end;
- until (temp>=lobound) and (temp<=hibound);
- number:=temp;
- end;
-
- procedure readint;
-
- var
- i,maxlen:byte;
- temp:longint;
- ch:char;
- s:string[6];
- error:integer;
-
- begin
- if hibound<lobound then exit;
- str(lobound,s);
- maxlen:=length(s); { Maximum width needed is the width of the }
- str(hibound,s); { lobound or the hibound, whichever is wider }
- if length(s)>maxlen then maxlen:=length(s);
- repeat { Same type of loop-within-loop as in previous procedure }
- s:='';
- repeat
- ch:=getkey;
- case ch of
- '-' : if length(s)=0 then begin
- s:='-'; { minus sign allowed if it is the first character in s }
- write('-');
- end;
- '0'..'9' : if (length(s)<maxlen) then begin
- s:=s+ch;
- write(ch)
- end;
- #8 : if length(s)>0 then begin
- delete(s,length(s),1);
- backup(1);
- write(' ');
- backup(1);
- end;
- #13 : if length(s)=0 then exit;
- end
- until ch=#13;
- val(s,temp,error);
- if (temp<lobound) or (temp>hibound) then begin
- beep;
- backup(length(s));
- for i:=1 to length(s) do write(' ');
- backup(length(s));
- end;
- until (temp>=lobound) and (temp<=hibound);
- number:=temp;
- end;
-
- procedure readreal;
-
- var
- i,maxlen:byte;
- temp:real;
- ch:char;
- s:string;
- error:integer;
-
- begin
- if hibound<lobound then exit;
- str(lobound:1:decimals,s);
- maxlen:=length(s); { Maximum width is the wider of the hibound and }
- str(hibound:1:decimals,s); { the lobound with the appropriate decimals }
- if length(s)>maxlen then maxlen:=length(s);
- repeat { Again, same loop-within-loop }
- s:='';
- repeat
- ch:=getkey;
- case ch of
- '-' : if length(s)=0 then begin
- s:='-'; { minus sign allowed if it is the first character in s }
- write('-');
- end;
- '.' : if (pos('.',s)=0) and (length(s)<maxlen) then begin
- s:=s+'.'; { decimal pt. allowed if there is not already one in s }
- write('.');
- end;
- '0'..'9' : if length(s)<maxlen then begin
- s:=s+ch;
- write(ch)
- end;
- #8 : if length(s)>0 then begin
- delete(s,length(s),1);
- backup(1);
- write(' ');
- backup(1);
- end;
- #13 : if length(s)=0 then exit;
- end
- until ch=#13;
- val(s,temp,error);
- if (temp<lobound) or (temp>hibound) then begin
- beep;
- backup(length(s));
- for i:=1 to length(s) do write(' ');
- backup(length(s));
- end;
- until (temp>=lobound) and (temp<=hibound);
- number:=temp;
- end;
-
- procedure editstr;
-
- var
- regs:registers;
- ch:char;
- n,position,startline,endline:byte;
- inson:boolean;
-
- procedure update(noblanks,stepsback,startpos:byte);
-
- { Update the string, starting at position startpos. Stepsback contains how
- many spaces to back up before starting the update. Noblanks contains how
- many blanks to write after the updated string is written. After writing
- the blanks (if any), the cursor is backed up to the end of the string. }
-
- var
- i:byte;
- temp:string;
-
- begin
- temp:=copy(s,startpos,length(s)-startpos+1);
- chgcursor($20,0);
- backup(stepsback);
- write(temp);
- for i:=1 to noblanks do write(' ');
- backup(length(temp)-stepsback+noblanks);
- if inson then chgcursor(4,7) else chgcursor(6,7); { set cursor type }
- end;
-
- procedure addchar;
-
- { add the character ch to the string, only if:
- - ch is not in the set charstoexclude of disallowed characters,
- - ch is either less than #128 or has been typed on the numeric keypad (to
- disallow special keys like F1 that are not trapped as editing keys), and
- - there is room to insert the character (if in insert mode) or to add it
- to the end of the string (if the cursor is at the end of the string) }
-
- begin
- if not (ch in charstoexclude) and (alttyped or (ch<#128))
- and ((length(s)<maxlen) or not inson and (position<length(s))) then begin
- write(ch);
- if inson or (position=length(s)) then begin
- insert(ch,s,position+1);
- if position<length(s)-1 then update(0,0,position+2);
- end else s[position+1]:=ch;
- inc(position);
- end; { echo the character, and insert it into the string if in insert mode
- or overwrite the character at the cursor if in overstrike mode }
- end;
-
- begin
- getcursor(startline,endline); { save cursor shape }
- inson:=false; { overstrike mode at first }
- chgcursor(6,7); { start with a thin cursor }
- position:=length(s); { put cursor at end of string }
- write(s); { write out the initial string }
- charstoexclude:=charstoexclude+[^G,^J,^Z];
- { these characters won't display, so make sure they are excluded }
- repeat
- gotoxy(wherex,wherey); { This removed a problem with updating the cursor on
- my screen, for some reason. Something in my ANSI driver, I think. }
- ch:=getkey;
- case ch of
- ^H : if (length(s)>0) and (position>0) then begin
- delete(s,position,1);
- update(1,1,position);
- dec(position);
- backup(1);
- end; { backspace }
- ^I : if not alttyped and (position<length(s)-4) then begin
- for n:=1 to 5 do if wherex=screenwidth
- then gotoxy(1,wherey+1)
- else gotoxy(wherex+1,wherey);
- inc(position,5);
- end; { tab key moves cursor forward five spaces }
- ^M : begin
- chgcursor($20,0);
- backup(position);
- write(s);
- end; { do final update before exiting }
- ^[ : begin
- n:=length(s);
- s:='';
- update(n,position,1);
- chgcursor($20,0);
- backup(position);
- position:=0;
- if inson then chgcursor(4,7) else chgcursor(6,7);
- end; { ESC key--clear out string }
- ins : if alttyped then addchar else begin
- inson:=not inson;
- if inson then chgcursor(4,7) else chgcursor(6,7);
- end;
- del : if alttyped then addchar else
- if (length(s)>0) and (position<length(s)) then begin
- delete(s,position+1,1);
- update(1,0,position+1);
- end;
- cntlhome : if alttyped then addchar else
- if (length(s)>0) and (position>0) then begin
- delete(s,1,position);
- update(position,position,1);
- chgcursor($20,0);
- backup(position);
- position:=0;
- if inson then chgcursor(4,7) else chgcursor(6,7);
- end; { delete from cursor to beginning of string }
- cntlend : if alttyped then addchar else
- if (length(s)>0) and (position<length(s)) then begin
- n:=length(s)-position;
- delete(s,position+1,n);
- update(n,0,position+1);
- end; { delete from cursor to end of string }
- home : if alttyped then addchar else begin
- chgcursor($20,0);
- backup(position);
- position:=0;
- if inson then chgcursor(4,7) else chgcursor(6,7);
- end;
- end_ : if alttyped then addchar else begin
- chgcursor($20,0);
- backup(position);
- write(s);
- if inson then chgcursor(4,7) else chgcursor(6,7);
- position:=length(s);
- end;
- reversetab: if not alttyped and (position>4) then begin
- backup(5);
- dec(position,5);
- end; { reverse tab backs the cursor up five spaces }
- leftarrow : if alttyped then addchar else if position>0 then begin
- backup(1);
- dec(position);
- end;
- rightarrow: if alttyped then addchar else if position<length(s) then begin
- if wherex=screenwidth
- then gotoxy(1,wherey+1) { wrap to next line if at end }
- else gotoxy(wherex+1,wherey);
- inc(position);
- end;
- uparrow: if alttyped then addchar else
- if position>=screenwidth then begin
- dec(position,screenwidth);
- gotoxy(wherex,wherey-1);
- end; { go up one line }
- downarrow: if alttyped then addchar else
- if position+screenwidth<=length(s) then begin
- inc(position,screenwidth);
- gotoxy(wherex,wherey+1);
- end; { go down one line }
- else addchar; { character is not an editing key, add it to the string }
- end;
- until ch=#13; { many keys have "if alttyped then addchar else ..." after
- them; this means that if the key was typed on the numeric keypad, that it
- should be taken literally and added to the string rather than being
- interpreted as an editing key }
- chgcursor(startline,endline); { restore cursor to the way it was }
- end;
-
- procedure readstr;
-
- { quite simple; just call editstr with an initially null string and return
- the new string if it was changed }
-
- var temp:string;
-
- begin
- temp:='';
- editstr(temp,maxlen,charstoexclude);
- if temp>'' then s:=temp;
- end;
-
- procedure flushbuffer;
-
- var regs:registers;
-
- begin
- regs.ah:=$C;
- regs.al:=0; { al=0 means don't do anything after flushing buffer }
- msdos(regs); { Call DOS function 12--flush stdin buffer }
- end;
-
- { The next four routines affect keyboard toggle states. They should be used
- sparingly, if at all. The states are affected by toggling the appropriate
- bit in the keyboard flag byte. }
-
- procedure setcapslock;
-
- begin
- if state then keyflag:=keyflag or $40 else keyflag:=keyflag and $BF;
- end;
-
- procedure setnumlock;
-
- begin
- if state then keyflag:=keyflag or $20 else keyflag:=keyflag and $DF;
- end;
-
- procedure setscrolllock;
-
- begin
- if state then keyflag:=keyflag or $10 else keyflag:=keyflag and $EF;
- end;
-
- procedure setinsert;
-
- begin
- if state then keyflag:=keyflag or $80 else keyflag:=keyflag and $7F;
- end;
-
- function getcapslock;
-
- var regs:registers;
-
- begin
- regs.ah:=2;
- intr($16,regs); { Call BIOS int 16h, function 2--get keyboard shift status }
- getcapslock:=regs.al and 64=64; { Bit 6 contains caps lock status }
- end;
-
- function getnumlock;
-
- var regs:registers;
-
- begin
- regs.ah:=2;
- intr($16,regs); { Call BIOS int 16h, function 2--get keyboard shift status }
- getnumlock:=regs.al and 32=32; { Bit 5 contains num lock status }
- end;
-
- function getscrolllock;
-
- var regs:registers;
-
- begin
- regs.ah:=2;
- intr($16,regs); { Call BIOS int 16h, function 2--get keyboard shift status }
- getscrolllock:=regs.al and 16=16; { Bit 4 contains scroll lock status }
- end;
-
- function getinsert;
-
- var regs:registers;
-
- begin
- regs.ah:=2;
- intr($16,regs); { Call BIOS int 16h, function 2--get keyboard shift status }
- getinsert:=regs.al and 128=128; { Bit 7 contains insert status }
- end;
-
- function rightshiftdown;
-
- var regs:registers;
-
- begin
- regs.ah:=2;
- intr($16,regs); { Call BIOS int 16h, function 2--get keyboard shift status }
- rightshiftdown:=regs.al and 1=1; { Bit 0 contains right shift status }
- end;
-
- function leftshiftdown;
-
- var regs:registers;
-
- begin
- regs.ah:=2;
- intr($16,regs); { Call BIOS int 16h, function 2--get keyboard shift status }
- leftshiftdown:=regs.al and 2=2; { Bit 1 contains right shift status }
- end;
-
- function shiftdown;
-
- var regs:registers;
-
- begin
- regs.ah:=2;
- intr($16,regs); { Call BIOS int 16h, function 2--get keyboard shift status }
- shiftdown:=regs.al and 3<>0; { Check either bit 0 or 1 }
- end;
-
- function controldown;
-
- var regs:registers;
-
- begin
- regs.ah:=2;
- intr($16,regs); { Call BIOS int 16h, function 2--get keyboard shift status }
- controldown:=regs.al and 4=4; { Bit 2 contains control status }
- end;
-
- function altdown;
-
- var regs:registers;
-
- begin
- regs.ah:=2;
- intr($16,regs); { Call BIOS int 16h, function 2--get keyboard shift status }
- altdown:=regs.al and 8=8; { Bit 3 contains alt status }
- end;
-
- procedure chgcursor;
-
- var regs:registers;
-
- begin
- with regs do begin
- ah:=1;
- ch:=startline;
- cl:=endline;
- end;
- intr($10,regs); { Call BIOS int 10h, function 1--set cursor shape }
- end;
-
- procedure getcursor;
-
- var regs:registers;
-
- begin
- with regs do begin
- ah:=$F;
- intr($10,regs); { Get correct display page into bh }
- ah:=3;
- intr($10,regs); { Call BIOS int 10h, function 3--get cursor shape }
- startline:=ch;
- endline:=cl;
- end;
- end;
-
- end.