Code:
' FILE : EDIT$U.BAS ' PURPOSE : Make A "Unit" out of SUB Editstring ' COPYRIGHT: Placed in the public domain by the author, Michael Mattias. ' USAGE: ' Place cursor on correct ROW ' CALL EditString (Text$, LeftCol%, MaxSize%, KeyCode%, Upper) ' Text% = string to be edited (default value) ' LeftCol% = column where string starts ' MaxSize% = maximum length permitted. (Beeps if attemt to execeed) ' KeyCode% = Value of key used to exit edit routine (see equates) ' Upper% = Convert all letters to uppercase if non-zero ' HISTORY ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ' 01.21.92 Coded as unit PB 2.1 ' 03.13.93 brought into PB3 ' 01.20.94 eliminated EXTERNAL ESColorScreen ' 09.09.94 problem with cursor was that I had the BIOS int h&10 reporting ' color when it should be mono. Fixed. Then I changed the cursor ' to make the insert cursor the small line, and the overwrite ' cursor the block. '12.27.95 Move to PB 3.2 '11.01.98 Move to PB/DOS 3.5 ' ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ' Valid values for $STACK are 1536 thru 32766 (decimal) $LIB COM-, IPRINT+, GRAPH-, CGA-, LPT-, FULLFLOAT- $ERROR ALL OFF '$LIB options include: ' COM - Serial communications support ' LPT - line printer support ' GRAPH - all graphics If a certain graphics is enabled, ' CGA all subordinate graphics are also ' EGA enabled. Priority is CGA,EGA,VGA; ' VGA HERC is independent. GRAPH- and CGA- do ' HERC permit the use of COLOR statements 'FULLFLOAT - full floating point emulation ' ALL - all the above '$FLOAT PROCEDURE ' $FLOAT options are: ' PROCEDURE - larger but faster than EMULATE; runs on any CPU ' EMULATE - smaller but slower than EMULATE ' NPX - runs only on 80x87, 80386 and 80486 processors $OPTION AUTODIM-, CNTLBREAK+ $COMPILE UNIT DEFINT A - Z ' Variables are Integer unless overridden '======= End Standard Materials ========================================== ProgramConstants: '======== Named Program Constants ============ %FALSE = 0 : %TRUE = NOT %FALSE %Home = -71 ' Cursor Movement Keys %EndKey = -79 ' used in SUB %LeftArrow = -75 %RightArrow = -77 %UpArrow = -72 %DownArrow = -80 %Escape = 27 %PageUp = -73 %PageDown = -81 %Insert = -82 %Delete = -83 %F5Key = -63 %F9Key = -67 %F10Key = -68 %CR = 13 ' Carriage return %LF = 10 ' Line feed %DBSpace = 8 ' destructive backspace '====== End Named Program Constants ========== SharedDataNames: ' ========= SHARED Data Names ==================== 'EXTERNAL ESColorScreen 'eliminated 1/20/94 ' ======== End SHARED Data Names ================= 'ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» 'º SUB TO EDIT Text Strings SUB EditString º 'ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ SUB EditString (Text$, LeftCol%, MaxSize%, KeyCode%, Upper) PUBLIC ' NOTE : Modified 8.29.91 to pass "Upper". If Upper = NOT 0, THEN ' all letters will be capitalized LOCAL Edit$,TextPos%, Ky$ , RightCol%, TopScan%, BottomScan%, Xin%, HoldY LOCAL AL STATIC Inserting%, CursorSize%, BeenHere% ' Use BIOS interrupt 10h service 3 to get/ save incoming cursor shape ' INPUT : BH = Page number AH = 3 ' OUTPUT : DH,DL = Current Row, Column; CH,CL = cursor top,bottom ' REG 1, &h0300 ' set AH REG 2, &h0000 ' set BH to page 0 ( default) CAll Interrupt &h10 TopScan% = Reg(3) \ &hFF ' high byte (CH) BottomScan% = Reg(3) AND &h00FF ' low byte (CL) Xin% = POS(0) ' save cursor X at entry RightCol% = LeftCol% + MaxSize% - 1 ' set up text area IF BeenHere% = %FALSE THEN ' preserve insert/cursor size BeenHere% = %TRUE ' relationship from last time REG 1, &h0F00 ' use BIOS to get color/mono CALL INTERRUPT &h10 ' on first use only AL = REG(1) AND &hFF IF AL = 7 THEN ' MONO monitor (fixed 9/9/94) CursorSize% = 12 ' Monochrome uses 13 scan lines ELSE ' (numbered 0 to 12) CursorSize% = 7 ' Color uses 8 (0 to 7) END IF Inserting% = %TRUE ' my preferred default END IF Edit$ = LEFT$(Text$ + SPACE$(Maxsize%), MaxSize%) 'space pad the text to 'the max field size ' TextPos% = POS(0) - LeftCol% + 1 'Get the cursor's location to ' IF TextPos% < 1 THEN TextPos% = 1 'see where to begin editing ' IF TextPos% > LEN(Edit$) THEN TextPos% = LEN(Edit$) LOCATE , LeftCol% ' go to beg of field HoldY = CSRLIN ' save this to check for linewrap PRINT Edit$; ' and put up the string LOCATE HoldY, LeftCol% ' restore cursor to beg of line ' done for linewrap situation IF Inserting% THEN ' present correct cursor LOCATE ,,,CursorSize% -1, CursorSize% ' single line cursor for insert mode ELSE LOCATE ,,, CursorSize% \ 2, CursorSize% ' block for overwrite END IF ' Insert this para to have editing start at other than start of field. ' requires NoHome% be EXTERNAL or added to call parameters ' If NoHome% THEN ' TextPos% = Xin% ' set by calling sub ' ELSE ' not coming from editscreen ' TextPos% = 1 ' END IF '----- Main loop for handling key presses DO LOCATE , LeftCol% + TextPos% - 1, 1 'Locate the cursor, turn it on DO 'Wait for a key press Ky$ = INKEY$ LOOP UNTIL LEN(Ky$) Upper1: IF Upper THEN Ky$ = UCASE$(Ky$) IF LEN(Ky$) = 1 THEN 'Make a key code from Ky$ KeyCode% = ASC(Ky$) 'Single character key ELSE KeyCode% = -ASC(RIGHT$(Ky$, 1)) 'Extended keys are negative END IF '----- Branch according to the key pressed SELECT CASE KeyCode% CASE %DBSpace 'Destructive BS IF LeftCol% + TextPos% -1 > 1 THEN ' if left col is at 1 TextPos% = TextPos% - 1 'Back up the text pointer LOCATE , LeftCol% + TextPos% - 1, 0 'Locate 1 to the left IF TextPos% > 0 THEN 'Still within the field? IF Inserting% THEN 'Truncate the string MID$(Edit$, TextPos%) = MID$(Edit$, TextPos% + 1) + " " ELSE 'Blank the letter MID$(Edit$, TextPos%) = " " END IF HoldY = CSRLIN 'for linewrap PRINT MID$(Edit$, TextPos%); 'Print new part of text LOCATE HoldY ' restore if Line Wrap ELSE ' we're at start of field INCR TextPos% ' reset Beep END IF ELSE ' trying DBSpace at 1 BEEP END IF CASE %CR,%Escape,%UpArrow, %DownArrow EXIT LOOP ' Bail out CASE 32 TO 254 ' printable characters LOCATE , , 0 ' Turn the cursor off HoldY = CSRLIN ' for linewrap! IF Inserting% THEN ' Expand the text string MID$(Edit$, TextPos%) = Ky$ + MID$(Edit$, TextPos%) PRINT MID$(Edit$, TextPos%); ' Print the expanded part ELSE MID$(Edit$, TextPos%) = Ky$ 'Put the new letter in string PRINT Ky$; 'Print the letter END IF LOCATE HoldY ' fix if linewrap IF TextPos% <> LEN(Edit$) THEN INCR TextPos% 'Increment the text pointer END IF ' if not at end CASE %LeftArrow IF TextPos% = 1 THEN BEEP ELSE DECR TextPos% 'Decrement text pointer END IF CASE %RightArrow IF Textpos% = LEN(Edit$) THEN BEEP ELSE INCR TextPos% 'Increment text pointer END IF CASE %Home TextPos% = 1 'Move text pointer to 1 CASE %EndKey FOR N% = LEN(Edit$) TO 1 STEP -1 'Look backwards for non-blank IF MID$(Edit$, N%, 1) <> " " THEN EXIT FOR NEXT N% TextPos% = N% + 1 'Set pointer to last char +1 IF TextPos% > LEN(Edit$) THEN TextPos% = LEN(Edit$) CASE %Insert Inserting% = NOT Inserting% 'Toggle the Insert state IF Inserting% THEN 'Adjust the cursor size LOCATE , , , CursorSize% - 1, CursorSize% ELSE LOCATE , , , CursorSize% \ 2, CursorSize% END IF CASE %Delete 'Truncate the text MID$(Edit$, TextPos%) = MID$(Edit$, TextPos% + 1) + " " LOCATE , , 0 'Print the truncated part HoldY = CSRLIN PRINT MID$(Edit$, TextPos%); LOCATE HoldY CASE ELSE 'All other keys, EXIT LOOP ' bail out END SELECT LOOP ' In here, we could strip trailing blanks. That way you always pass the data, ' and get back the data. Also, we should restore the incoming cursor shape. Text$ = Edit$ ' set the text to new value ' Restore the incoming cursor .... LOCATE ,,,TopScan%, BottomScan% END SUB