' MOUSTEST.BAS : shows how to implement the mouse in a program ' Author : Egbert Zijlema (E.Zijlema@uni4nn.iaf.nl) ' Date : July 23, 1996 ' Language : Power Basic 3.2 ' Copyright status: Public Domain ' Introduction: ' Routines concerning the status of the mouse are basically very simple. ' They are all done by calling INTERRUPT &H33. Depending of the value ' passed through the AX-register one can test the presence of the mouse ' driver, show/hide the mouse cursor, define a limited screen area, ' and so forth. ' But unfortunately all those well known routines don't tell you how to ' implement the mouse in your program. How, for instance, do you tell ' your software that clicking on the word "File" in the menu bar means ' the same as pressing Alt-f (to pull down the File menu)? ' This demo shows how to select a file from a list of 24 filenames ' either by the mouse or the arrow keys. ' Credit: ' The INTERRUPT-routines, written in assembly, are from Dave Navarro. ' They came with Power Basic 3.2 (MOUSUNIT.BAS in the EXAMPLE ' subdirectory). I took the liberty to add 2 'flags' to those routines, ' one for the presence of the driver and one for the hide/show status of ' the cursor. The benefit of the first is obvious: you only need 1 test ' for the presence of the mousedriver. The purpose of the second is ' to avoid switching on/off the cursor more than once. This is rather ' crucial, due to the fact that the mouse is counting, not toggling, its ' on/off status. If you accidently should hide the mouse twice, you MUST ' also do the opposite twice in order to make it visible again. DEFINT A - Z TYPE MOUSEFLAGS mouse AS INTEGER ' mouse driver present mseon AS INTEGER ' mouse cursor on/off END TYPE DIM mflg AS SHARED MOUSEFLAGS DIM VideoAddress AS SHARED INTEGER DIM FileName(1 : 24) AS SHARED STRING IF (pbvScrnCard AND 1) = 0 THEN VideoAddress = &HB800 ' color card ELSE VideoAddress = &HB000 ' monochrome END IF IF MsThere THEN mflg.mouse = -1 ' mouse driver present DIM matrix(1 : 25, 1 : 80) AS SHARED INTEGER ' screen matrix 2000 cells END IF ' equates for arrow keys: %HOME = 71 * 256 : %UP = 72 * 256 : %LEFT = 75 * 256 %RIGHT = 77 * 256 : %END = 79 * 256 : %DOWN = 80 * 256 FUNCTION MsThere AS INTEGER ! push DS ; save DS for PowerBASIC ! xor AX, AX ; clear AX ! int &H33 ; call mouse driver ! xor BX, BX ; clear BX, assume no mouse present ! or AX, AX ; does AX = 0? ! jz MsThereDone ; yes, we're done ! dec BX ; no, make it -1 MsThereDone: ! mov FUNCTION, BX ; put BX in RetVal variable ! pop DS ; restore DS END FUNCTION FUNCTION GetMouseOrKey STATIC oldKey MsStatus oldButn, dummy, dummy DO MsStatus buttons, row, col IF INSTAT THEN oldKey = CVI( INKEY$ + CHR$(0) ) FUNCTION = oldKey EXIT FUNCTION ELSEIF (buttons = 1) AND (matrix(row, col) <> oldKey) THEN oldKey = matrix(row, col) FUNCTION = oldKey EXIT FUNCTION END IF LOOP UNTIL (oldButn = 1) AND (buttons = 0) oldKey = 13 : FUNCTION = 13 END FUNCTION SUB MsCursorOn IF NOT mflg.mouse THEN EXIT SUB ' no mouse, so quit IF NOT mflg.mseon THEN ' only if mouse off ! push DS ; save DS for PowerBASIC ! mov AX, 1 ; mouse driver function 1, turn on cursor ! int &H33 ; call driver ! pop DS ; restore DS mflg.mseon = -1 ' mouse cursor on END IF END SUB SUB MsCursorOff IF NOT mflg.mouse THEN EXIT SUB IF mflg.mseon THEN ! push DS ; save DS for PowerBASIC ! mov AX, 2 ; mouse driver function 2, turn off cursor ! int &H33 ; call driver ! pop DS ; restore DS mflg.mseon = 0 ' mouse cursor off END IF END SUB SUB MsStatus(buttons AS INTEGER, row AS INTEGER, col AS INTEGER) IF NOT mflg.mouse THEN EXIT SUB ! push DS ; save DS for PowerBASIC ! mov AX, &H03 ; function 03h, get mouse status ! int &H33 ; call mouse interrupt ! les DI, buttons ; point ES:DI to buttons ! mov ES:[DI], BX ; put active button(s) in variable ! les DI, row ; point ES:DI to Row ! mov ES:[DI], DX ; put mouse row in variable ! les DI, col ; point ES:DI to Column ! mov ES:[DI], CX ; put mouse column in variable ! pop DS ; restore DS for PowerBASIC IF (pbvScrnMode = 7) OR (pbvScrnMode = 0) THEN row = (row \ 8) + 1 ' if text mode, then fix coordinates col = (col \ 8) + 1 END IF END SUB SUB MsSetWindow(BYVAL Row AS INTEGER, BYVAL Col AS INTEGER, _ BYVAL Rows AS INTEGER, BYVAL Cols AS INTEGER) IF NOT mflg.mouse THEN EXIT SUB Rows = Row + Rows - 1 ' adjust rows to real coordinates Cols = Col + Cols - 1 ' adjust cols to real coordinates IF (pbvScrnMode = 7) OR (pbvScrnMode = 0) THEN Row = Row * 8 ' if text mode, adjust coordinates Rows = Rows * 8 Col = Col * 8 Cols = Cols * 8 END IF ! push DS ; save DS for PowerBASIC ! mov CX, Row ; put start row in CX ! mov DX, Rows ; put end row in DX ! mov AX, &H08 ; function 08h, set vertical limit ! int &H33 ; call mouse interrupt ! mov CX, Col ; put start column in CX ! mov DX, Cols ; put end column in DX ! mov AX, &H07 ; function 07h, set horizontal limit ! int &H33 ; call mouse interrupt ! pop DS ; restore DS for PowerBASIC END SUB SUB CollectFileNames SHARED PrimaryScreen$ FileToFind$ = DIR$("C:\DOS\*.*") DO WHILE LEN(FileToFind$) INCR count FileName(count) = FileToFind$ IF count = UBOUND(FileName) THEN EXIT DO ' no more than 24 names FileToFind$ = DIR$ LOOP ' and display them COLOR 15, 0 row = 2 : col = 4 FOR count = 1 TO UBOUND(FileName) LOCATE row, col PRINT FileName(count) FOR cell = col TO col + LEN(FileName(count)) - 1 matrix(row, cell) = count + 256 ' don't use ASCII! NEXT INCR col, 14 IF col = 60 THEN INCR row : col = 4 END IF NEXT ' finally save the screen DEF SEG = VideoAddress PrimaryScreen$ = PEEK$(0, 4000) DEF SEG END SUB SUB SelectionMenu SHARED PrimaryScreen$ STATIC selected IF selected = 0 THEN selected = 1 GOSUB inverse DO MsSetWindow 1, 3, 6, 54 MsCursorOn modified = 0 action = GetMouseOrKey SELECT CASE action CASE 27 selected = 0 EXIT LOOP CASE %LEFT IF selected > 1 THEN DECR selected modified = -1 END IF CASE %RIGHT IF selected < UBOUND(FileName) THEN INCR selected modified = -1 END IF CASE %HOME IF selected > 1 THEN selected = 1 modified = -1 END IF CASE %END IF selected < UBOUND(FileName) THEN selected = UBOUND(FileName) modified = -1 END IF CASE %UP IF selected > 4 THEN DECR selected, 4 modified = -1 END IF CASE %DOWN IF selected < UBOUND(FileName) - 3 THEN INCR selected, 4 modified = -1 END IF CASE 257 TO UBOUND(FileName) + 256 selected = action - 256 modified = -1 END SELECT IF modified THEN GOSUB inverse LOOP UNTIL action = 13 ' until ENTER is pressed MsCursorOff DEF SEG = VideoAddress POKE$ 0, PrimaryScreen$ DEF SEG COLOR 15, 0 LOCATE 25,4 PRINT "You selected "; IF selected = 0 THEN PRINT "nothing"; ELSE PRINT CHR$(34);FileName(selected);CHR$(34); END IF EXIT SUB inverse: MsCursorOff DEF SEG = VideoAddress POKE$ 0, PrimaryScreen$ DEF SEG factor = selected - 1 hor = 2 + factor \ 4 vert = 4 + (factor MOD 4) * 14 COLOR 0, 7 LOCATE hor, vert : PRINT FileName(selected) RETURN END SUB SUB MainMenu DO COLOR 7, 0 LOCATE 20, 4 : PRINT "Press any arrow key to select; ESC to quit" KeyIn = GetMouseOrKey SELECT CASE KeyIn CASE 27 ' Escape pressed COLOR 7, 0 CLS SYSTEM CASE %RIGHT, %LEFT, %UP, %DOWN ' any arrow key COLOR 7, 0 LOCATE 25, 1 : PRINT SPACE$(80); CALL SelectionMenu END SELECT LOOP END SUB ' sample main CLS CollectFileNames MainMenu END