CON ''=====< GUI Base >======================================================= '' '' =========================================================================== '' VGA High-Res Text UI Elements Base UI Support Functions v1.2 '' '' File: GUIBase.spin '' Author: Allen Marincak '' Copyright (c) 2009 Allen MArincak '' See end of file for terms of use '' =========================================================================== CON '--------------------------------------------------------------------------- ' GUI Element Inventory '--------------------------------------------------------------------------- ' User modifies these as required by the GUI application being written. ' These constants describe how many elements of each type are required. Set ' any you do not need to 1. You can't set it to 0 because there is no ' conditional compilation for SPIN so I can't avoid NULL references. '-------------------------------------------------------------------------- GZ_SPIN = 2 'number of SPIN controls GZ_CHKB = 4 'number of Check Boxes GZ_RADB = 6 'number of Radio Buttons GZ_TBOX = 3 'number of Text Boxes GZ_MENU = 6 'number of Menu Items GZ_INPF = 3 'number of Input Fields GZ_PUSH = 3 'number of pushbuttons GZ_STAT = 2 'number of Status Lamps '--------------------------------------------------------------------------- ' Do not modify any of the constants below '--------------------------------------------------------------------------- GZ_TOTAL = GZ_SPIN+GZ_CHKB+GZ_RADB+GZ_TBOX+GZ_MENU+GZ_INPF+GZ_PUSH+GZ_STAT GID_SPIN = $0100 'types GID_CHKB = $0200 GID_RADB = $0300 GID_TBOX = $0400 GID_MENU = $0500 GID_INPF = $0600 GID_PUSH = $0700 GID_STAT = $0800 G_INIT = $8000 G_IMSK = $7F00 G_OMSK = $00FF VGACOLS = SVGA#cols VGAROWS = SVGA#rows OBJ '--------------------------------------------------------------------------- ' required driver objects, keep these '--------------------------------------------------------------------------- SVGA : "vga_hires_text" MOUS : "mouse" KEYB : "Keyboard" 'only needed if using the Input Field Object '--------------------------------------------------------------------------- ' UI element objects ' ' You will need to comment out elements for which you set the number to 0, ' the compiler will issue an error for 0 sized arrays. ' ' Note that the SBOX object (Simple Box) is used by several other objects so ' do not comment out that one (it is miniscule anyway) '--------------------------------------------------------------------------- SPIN[GZ_SPIN] : "SpinBox" CHKB[GZ_CHKB] : "RadioCheck" RADB[GZ_RADB] : "RadioCheck" TBOX[GZ_TBOX] : "TextBox" MENU[GZ_MENU] : "MenuItem" INPF[GZ_INPF] : "InputField" PUSH[GZ_PUSH] : "PushButton" STAT[GZ_STAT] : "StatusLamp" SBOX : "SimpleBox" VAR long scrn[VGACOLS*VGAROWS/4] 'screen buffer - could be bytes, but longs allow more efficient scrolling word colors[VGAROWS] 'row colors long sync 'sync long - written to -1 by VGA driver after each screen refresh byte cx0,cy0,cm0,cx1,cy1,cm1 'cursor control bytes long liveINPF 'currently active Input Field (has keyboard focus) word gz_elem[GZ_TOTAL] 'element management array byte gz_groups[GZ_RADB] 'radio button group control CON ''=====< GUI Base Functions >============================================= ' ' NOTE Do not modify anything below unless you wish ot add or ' make changes to the GUI functionality '------------------------------------------------------------------------- PUB Init( vgaBasePin, MouseDatPin, MouseClkPin, KeyboardDatPin, KeyboardClkPin ) | idx, gdx 'Initializes the VGA, Mouse and Keyboard Drivers as well as basic GUI parameters ' ' vgaBasePin - start of 8 consecutive pins where the VGA H/W interface is ' MouseDatPin - the pin driving the mouse data line ' MouseClkPin - the pin driving the mouse clock line ' KeyboardDatPin - the pin driving the keyboard data line ' KeyboardClkPin - the pin driving the keyboard clock line ' 'Returns the screen geometry in a WORD ' high byte = number of character rows ' low byte = number of cgaracter columns '--------------------------------------------------------------------------- ' Start VGA, Mouse and Keyboard Drivers '--------------------------------------------------------------------------- cx1 := 0 'text cursor starting position cy1 := 3 ' (but hidden at start) SVGA.start(vgaBasePin,@scrn,@colors,@cx0,@sync) 'start VGA HI RES TEXT driver MOUS.start(MouseDatPin, MouseClkPin) 'start mouse and set bound parameters MOUS.bound_limits(0, 0, 0, VGACOLS - 1, VGAROWS - 1, 0) MOUS.bound_scales(4, -7, 0) 'adjust speed/sensitivity to be a touch slower MOUS.bound_preset(2, 6, 0) 'mouse starting position KEYB.start( KeyboardDatPin, KeyboardClkPin ) 'start keyboard driver cm0 := %001 'set mouse cursor to be a solid block cm1 := %000 'set text cursor to be off for the moment ClearScreen( %%020, %%000 ) 'green on black each is %%RGB 4 levels per R-G-B '--------------------------------------------------------------------------- 'Prepare management and control array. This array has an entry for each 'element declared it maintains the status of each element and indices into 'the individual element arrays ' 'WORD format: aabb ' ' where aa = type with msb 0 = free 1 = set (initialized) ' bb = index to element array '--------------------------------------------------------------------------- gdx := 0 if GZ_SPIN repeat idx from 0 to GZ_SPIN - 1 gz_elem[gdx] := GID_SPIN + idx SPIN[idx].set_gzidx( gdx ) gdx++ if GZ_CHKB repeat idx from 0 to GZ_CHKB - 1 gz_elem[gdx] := GID_CHKB + idx CHKB[idx].set_gzidx( gdx ) gdx++ if GZ_RADB repeat idx from 0 to GZ_RADB - 1 gz_elem[gdx] := GID_RADB + idx RADB[idx].set_gzidx( gdx ) gdx++ if GZ_TBOX repeat idx from 0 to GZ_TBOX - 1 gz_elem[gdx] := GID_TBOX + idx TBOX[idx].set_gzidx( gdx ) gdx++ if GZ_MENU repeat idx from 0 to GZ_MENU - 1 gz_elem[gdx] := GID_MENU + idx MENU[idx].set_gzidx( gdx ) gdx++ if GZ_INPF repeat idx from 0 to GZ_INPF - 1 gz_elem[gdx] := GID_INPF + idx INPF[idx].set_gzidx( gdx ) gdx++ if GZ_PUSH repeat idx from 0 to GZ_PUSH - 1 gz_elem[gdx] := GID_PUSH + idx PUSH[idx].set_gzidx( gdx ) gdx++ if GZ_STAT repeat idx from 0 to GZ_STAT - 1 gz_elem[gdx] := GID_STAT + idx STAT[idx].set_gzidx( gdx ) gdx++ liveINPF := 0 return ( VGAROWS << 8 ) + VGACOLS PUB ProcessUI | retVal, gdx_in, odx, idx, tmp 'This function is the UI processing and control funtion. It must be executed 'often, regularly, and quickly. It should be placed in the application main 'loop and be allowed to run as often as possible to ensure a responsive UI ' 'This function will manage the UI and will return the unique id of the GUI 'element that requires an action (i.e. user clicked on an item or pressed 'enter in an Input Field). The value returned ( a GUID ) is the same value 'that was returned when the element was created via "Init" function (i.e. 'from GUI.SPINInit() or GUI.PUSHInit(), etc) retVal := -1 cx0 := MOUS.bound_x 'get mouse position to set cursor 0 position cy0 := MOUS.bound_y 'ALWAYS do this first '--------------------------------------------------------------------------- 'check if mouse over a control '--------------------------------------------------------------------------- gdx_in := IsIn( cx0, cy0 ) '--------------------------------------------------------------------------- 'on mouse left click perform UI action for selected element (if any) '--------------------------------------------------------------------------- if gdx_in <> -1 'if we are in a gui element if MOUS.button(0) 'if mouse left-click odx := gz_elem[gdx_in] & G_OMSK 'index to object array case gz_elem[gdx_in] & G_IMSK GID_SPIN: 'in Spin Control if SPIN[odx].Clicked(cx0,cy0)<>-1 ' - execute click on spin retVal := gdx_in GID_CHKB: 'in Check Box CHKB[odx].Select( -1 ) ' - toggle checkbox retVal := gdx_in GID_RADB: 'in Radio Button idx := 0 repeat GZ_RADB 'for each radio button if odx == idx RADB[idx].Select( 1 ) ' - toggle ON the selected one RADB[idx].DrawText( 1 ) else if gz_groups[odx] == gz_groups[idx] RADB[idx].Select( 0 ) ' - toggle OFF the others in this group RADB[idx].DrawText( 0 ) idx++ retVal := gdx_in GID_TBOX: 'in Text Box retVal := gdx_in GID_MENU: 'in Menu Item retVal := gdx_in GID_INPF: 'in Input Field idx := 0 repeat GZ_INPF 'for each input field if idx == odx INPF[idx].Select(1,@cx1,@cy1) liveINPF := idx cm1 := %111 'turn text cursor on, underscore slow blink else INPF[idx].Select(0,@cx1,@cy1) idx++ 'note no return for selecting INPF GID_PUSH: 'in Push Button retVal := gdx_in GID_STAT: 'in Status Lamp retVal := gdx_in repeat while MOUS.button(0) ' - wait for mouse release '--------------------------------------------------------------------------- 'Handle Keyboard input '--------------------------------------------------------------------------- if KEYB.gotkey idx := INPF[liveINPF].get_gzidx if gz_elem[idx] & G_INIT == G_INIT 'is it set tmp := INPF[liveINPF].Handler(KEYB.key) if tmp & $80000000 retVal := INPF[liveINPF].get_gzidx 'if enter was pressed return retVal PUB GetMouseXY 'Returns the mouse location in a WORD ' high byte = x location ' low byte = y location return ( cx0 << 8 ) + cy0 PRI IsIn( cx, cy ) | idx, gdx, retVal 'returns -1 if not in an element else a gui token (gz_elem[] array index) retVal := -1 if GZ_SPIN repeat idx from 0 to GZ_SPIN - 1 gdx := SPIN[idx].get_gzidx if gz_elem[gdx] & G_INIT == G_INIT 'is it set if SPIN[idx].IsIn( cx, cy ) retVal := SPIN[idx].get_gzidx if GZ_CHKB repeat idx from 0 to GZ_CHKB - 1 gdx := CHKB[idx].get_gzidx if gz_elem[gdx] & G_INIT == G_INIT 'is it set if CHKB[idx].IsIn( cx, cy ) retVal := CHKB[idx].get_gzidx CHKB[idx].DrawText( 1 ) else CHKB[idx].DrawText( 0 ) if GZ_RADB repeat idx from 0 to GZ_RADB - 1 gdx := RADB[idx].get_gzidx if gz_elem[gdx] & G_INIT == G_INIT 'is it set if RADB[idx].IsIn( cx, cy ) retVal := RADB[idx].get_gzidx RADB[idx].DrawText( 1 ) else RADB[idx].DrawText( 0 ) if GZ_TBOX repeat idx from 0 to GZ_TBOX - 1 gdx := TBOX[idx].get_gzidx if gz_elem[gdx] & G_INIT == G_INIT 'is it set if TBOX[idx].IsIn( cx, cy ) retVal := TBOX[idx].get_gzidx if GZ_MENU repeat idx from 0 to GZ_MENU - 1 gdx := MENU[idx].get_gzidx if gz_elem[gdx] & G_INIT == G_INIT 'is it set if MENU[idx].IsIn( cx, cy ) retVal := MENU[idx].get_gzidx MENU[idx].DrawText( 1 ) else MENU[idx].DrawText( 0 ) if GZ_INPF repeat idx from 0 to GZ_INPF - 1 gdx := INPF[idx].get_gzidx if gz_elem[gdx] & G_INIT == G_INIT 'is it set if INPF[idx].IsIn( cx, cy ) retVal := INPF[idx].get_gzidx if GZ_PUSH repeat idx from 0 to GZ_PUSH - 1 gdx := PUSH[idx].get_gzidx if gz_elem[gdx] & G_INIT == G_INIT 'is it set if PUSH[idx].IsIn( cx, cy ) retVal := PUSH[idx].get_gzidx PUSH[idx].DrawText( 1 ) else PUSH[idx].DrawText( 0 ) if GZ_STAT repeat idx from 0 to GZ_STAT - 1 gdx := STAT[idx].get_gzidx if gz_elem[gdx] & G_INIT == G_INIT 'is it set if STAT[idx].IsIn( cx, cy ) retVal := STAT[idx].get_gzidx return retVal CON ''=====< SIMPLE BOX INTERFACE FUNCTIONS >================================= PUB SBOXInit( pRow, pCol, pWidth, pHeight, pTitlePtr ) 'Creates box with specified width and text. Something like: ' ------------- ' | | - title area ( non-existant if no title supplied) ' ------------- ' | | ' | | - text area with optional scolling print capability ' | | ' ------------- ' ' pRow = row upper location ' pCol = col left location ' pWidth = width ' pHeight = height ' pTitlePtr = title text (text must be 2 less than width) ' ' NOTE: Columns must be LONG aligned to take advantage of the most efficient ' scrolling (via LONGMOVE). The start column must be on a long boundary ' (multiple of 4) and the width must be a multiple of 4. If print scrolling ' is not required this restriction can be ignored. ' ' NOTE: There is NO RETURN value from this call. Simple Boxes are not tracked, ' they are viaual element but are not active elements SBOX.DrawBox( pRow, pCol, pWidth, pHeight, pTitlePtr, @scrn, VGACOLS ) CON ''=====< SPIN BOX INTERFACE FUNCTIONS >=================================== PUB SPINInit( pRow, pCol, pWidth, pType, pNum, pDataPtr ) | idx, gdx, retVal 'Creates a spin button box with specified width and text. Something like: ' --------------------- ' | spin text |↑|↓| ' --------------------- ' ' pRow = row upper location ' pCol = col left location ' pWidth = width of the control in columns ' pType = 0 = text 1 = numeric ' pNum = number of data elements ' pDataPtr = pointer to data for spin control ' ' The Data for the spin control is stored in a DAT section. For text type ' the section will be a number of byte aligned strings, each with a null ' terminator. For numeric type the section will be a number of long aligned ' longs. ' 'Returns -1 if there are no more free elements in the SPIN object array ' guid on success which is unique and used to identify the specific ' instance of the control. retVal := -1 repeat idx from 0 to GZ_TBOX - 1 gdx := SPIN[idx].get_gzidx if gz_elem[gdx] & G_INIT == 0 'is it free retVal := gdx gz_elem[gdx] |= G_INIT 'mark it used SPIN[idx].Init( pRow, pCol, pWidth, pType, pNum, pDataPtr, @scrn, VGACOLS ) quit return retVal PUB SPINIsIn( guid ) | odx ' returns true if the mouse is inside the spin control ' false otherwise odx := gz_elem[guid] & G_OMSK return SPIN[odx].IsIn( MOUS.bound_x, MOUS.bound_y ) PUB SPINClicked( guid ) | odx 'checks where the mouse click ocurred and returns -1 if not on an UP or DOWN 'arrow otherwise it returns the zero based data index of the currently 'displayed data odx := gz_elem[guid] & G_OMSK return SPIN[odx].Clicked( MOUS.bound_x, MOUS.bound_y ) PUB SPINGetDataIndex( guid ) | odx 'returns the zero based index of the currently displayed data item odx := gz_elem[guid] & G_OMSK return SPIN[odx].GetDataIndex CON ''=====< CHECK BOX INTERFACE FUNCTIONS >================================== PUB CHKBInit( pRow, pCol, pTextWidth, pTextPtr ) | idx, gdx, retVal 'Creates a checkbox box at the specified location. 'Something like: ' ' X Text here ' ' where X is a check box symbol ' ' pRow = row upper location ' pCol = col left location ' pTextWidth = width of button text (MAX 15 characters) ' pTextPtr = checkbox text (MAX 15 characters) ' 'Returns -1 if there are no more free elements in the CHKB object array ' guid on success which is unique and used to identify the specific ' instance of the control. retVal := -1 repeat idx from 0 to GZ_CHKB - 1 gdx := CHKB[idx].get_gzidx if gz_elem[gdx] & G_INIT == 0 'is it free retVal := gdx gz_elem[gdx] |= G_INIT 'mark it used CHKB[idx].Init( pRow, pCol, pTextWidth, 0, pTextPtr, @scrn, VGACOLS ) quit return retVal PUB CHKBIsIn( guid ) | odx ' returns true if the mouse is inside the check box ' false otherwise odx := gz_elem[guid] & G_OMSK return CHKB[odx].IsIn( MOUS.bound_x, MOUS.bound_y ) PUB CHKBDrawText( guid, pMode ) | odx ' pMode 0 = 0 for normal ' = 1 for inverted odx := gz_elem[guid] & G_OMSK CHKB[odx].DrawText( pMode ) PUB CHKBSelect( guid, pSel ) | odx 'sel = 1 to select 0 to deselect -1 to toggle it odx := gz_elem[guid] & G_OMSK CHKB[odx].Select( pSel ) PUB CHKBIsSet( guid ) | odx 'returns the status of the button (set=true not set=false) odx := gz_elem[guid] & G_OMSK return CHKB[odx].isSet CON ''=====< RADIO BUTTON INTERFACE FUNCTIONS >=============================== PUB RADBInit( pRow, pCol, pTextWidth, pTextPtr, pGroupID ) | idx, gdx, retVal 'Creates a radio button at the specified location. 'Something like: ' ' X Text here ' ' where X is a radio button symbol ' ' pRow = row upper location ' pCol = col left location ' pTextWidth = width of button text (MAX 15 characters) ' pTextPtr = checkbox text (MAX 15 characters) ' pGroupID = the id of the radio button group that this button belongs to ' 'Returns -1 if there are no more free elements in the RADB object array ' guid on success which is unique and used to identify the specific ' instance of the control. retVal := -1 repeat idx from 0 to GZ_RADB - 1 gdx := RADB[idx].get_gzidx if gz_elem[gdx] & G_INIT == 0 'is it free retVal := gdx gz_elem[gdx] |= G_INIT 'mark it used RADB[idx].Init( pRow, pCol, pTextWidth, 1, pTextPtr, @scrn, VGACOLS ) gz_groups[idx] := pGroupID 'remember group button belongs to RB_GRP quit return retVal PUB RADBIsIn( guid ) | odx ' returns true if the mouse inside the radio button ' false otherwise odx := gz_elem[guid] & G_OMSK return RADB[odx].IsIn( MOUS.bound_x, MOUS.bound_y ) PUB RADBDrawText( guid, pMode ) | odx ' pMode 0 = 0 for normal ' = 1 for inverted odx := gz_elem[guid] & G_OMSK RADB[odx].DrawText( pMode ) PUB RADBSelect( guid, pSel ) | odx 'sel = 1 to select 0 to deselect -1 to toggle it odx := gz_elem[guid] & G_OMSK RADB[odx].Select( pSel ) PUB RADBIsSet( guid ) | odx 'returns the status of the button (set=true not set=false) odx := gz_elem[guid] & G_OMSK return RADB[odx].isSet CON ''=====< PUSH BUTTON INTERFACE FUNCTIONS >================================ PUB PUSHInit( pRow, pCol, pTextPtr ) | idx, gdx, retVal 'Creates a pushbutton at the specified location. 'Something like: ' --------------- ' |ttttttttttttttt| ' --------------- ' ' where t = button text (MAX 15 characters) ' ' pRow = row upper location ' pCol = col left location ' pTextPtr = push button text (MAX 15 characters + null terminator) ' 'Returns -1 if there are no more free elements in the PUSH object array ' guid on success which is unique and used to identify the specific ' instance of the control. retVal := -1 repeat idx from 0 to GZ_PUSH - 1 gdx := PUSH[idx].get_gzidx if gz_elem[gdx] & G_INIT == 0 'is it free retVal := gdx gz_elem[gdx] |= G_INIT 'mark it used PUSH[idx].Init( pRow, pCol, pTextPtr, @scrn, VGACOLS ) quit return retVal PUB PUSHIsIn( guid ) | odx ' returns true if the mouse is inside the push button ' false otherwise odx := gz_elem[guid] & G_OMSK return PUSH[odx].IsIn( MOUS.bound_x, MOUS.bound_y ) PUB PUSHDrawText( guid, pMode ) | odx 'draws the pusbutton text in normal or inverted video. ' mode bit 0 = 0 for normal ' = 1 for inverted odx := gz_elem[guid] & G_OMSK PUSH[odx].DrawText( pMode ) PUB PUSHSetText( guid, pPtr ) | odx 'sets new text for the pushbutton ' pPtr points to the text, it MUST be the same size (or less) as the text ' it is replacing odx := gz_elem[guid] & G_OMSK PUSH[odx].SetText( pPtr ) CON ''=====< TEXT BOX INTERFACE FUNCTIONS >=================================== PUB TBOXInit( pRow, pCol, pWidth, pHeight, pWrap, pTitlePtr ) | idx, gdx, retVal 'Creates a box with specified width and text. Something like: ' ------------- ' | | - title area ( non-existant if no title supplied) ' ------------- ' | | ' | | - text area with optional scolling print capability ' | | ' ------------- ' ' pRow = row upper location ' pCol = col left location ' pWidth = width ' pHeight = height ' pWrap = 0 = truncate 1 = wrap lines ' pTitlePtr = title text text (text must be 2 less than width ore 32 MAX) ' 'Returns -1 if there are no more free elements in the TBOX object array ' guid on success which is unique and used to identify the specific ' instance of the control. ' ' NOTE: Columns must be LONG aligned to take advantage of the most efficient ' scrolling (via LONGMOVE). The start column must be on a long boundary ' (multiple of 4) and the width must be a multiple of 4. If print scrolling ' is not required this restriction can be ignored. retVal := -1 repeat idx from 0 to GZ_TBOX - 1 gdx := TBOX[idx].get_gzidx if gz_elem[gdx] & G_INIT == 0 'is it free retVal := gdx gz_elem[gdx] |= G_INIT 'mark it used TBOX[idx].Init( pRow, pCol, pWidth, pHeight, pWrap, pTitlePtr, @scrn, VGACOLS ) quit return retVal PUB TBOXIsIn( guid ) | odx ' returns true if the mouse is inside the text box text area ' (i.e. excluding title area if there is one) ' false otherwise odx := gz_elem[guid] & G_OMSK return TBOX[odx].IsIn( MOUS.bound_x, MOUS.bound_y ) PUB TBOXClear( guid ) | odx 'clears the text box. odx := gz_elem[guid] & G_OMSK TBOX[odx].Clear PUB TBOXPrint( guid, pTxtPtr, pSize ) | odx 'Prints a line of text. Iif already at the last row the existing text is 'scrolled up one line first and the top line is removed. Inverted text is 'written with the high bit of each character set. If line wrap is enabled the 'lines that are wrapped are marked with a preceding inverted right arrow 'character (non-printable Ascii). Leading and trailing CRLF characters are 'stripped out. Any intra line CRLFs are ignored and will display as 'funny' 'characters. ' ' pTxtPtr = pointer to null terminated string ' size = 0 for null terminated strings ' = the string length for non-null terminated strings odx := gz_elem[guid] & G_OMSK TBOX[odx].Print( pTxtPtr, pSize ) PUB TBOXScroll( guid ) | odx 'scroll the test area up one line odx := gz_elem[guid] & G_OMSK TBOX[odx].Scroll PUB TBOXTitle( guid, pTxtPtr ) | strIdx, vgaIdx, odx 'replace the original titlebar caption with new text. If no title was declared 'on initialization then this method will do nothing ' ' pTxtPtr = pointer to text to place in titlebar odx := gz_elem[guid] & G_OMSK TBOX[odx].Title( pTxtPtr ) CON ''=====< MENU ITEM INTERFACE FUNCTIONS >================================== PUB MENUInit( pRow, pCol, pTextPtr ) | idx, gdx, retVal 'Creates a menu item at the specified location. 'Something like: ' StttttttttttttttS ' ' where S = space character ' t = character position (MAX 15 characters) ' ' pRow = row upper location ' pCol = col left location ' pTextPtr = menu item text (MAX 15 characters + null terminator) ' 'Returns -1 if there are no more free elements in the MENU object array ' guid on success which is unique and used to identify the specific ' instance of the control. retVal := -1 repeat idx from 0 to GZ_MENU - 1 gdx := MENU[idx].get_gzidx if gz_elem[gdx] & G_INIT == 0 'is it free retVal := gdx gz_elem[gdx] |= G_INIT 'mark it used MENU[idx].Init( pRow, pCol, pTextPtr, @scrn, VGACOLS ) quit return retVal PUB MENUIsIn( guid ) | odx ' returns true if the mouse is inside the menu item ' false otherwise odx := gz_elem[guid] & G_OMSK return MENU[odx].IsIn( MOUS.bound_x, MOUS.bound_y ) PUB MENUDrawText( guid, pMode ) | odx 'draws the menu item text in normal or inverted video. ' mode bit 0 = 0 for normal ' = 1 for inverted odx := gz_elem[guid] & G_OMSK MENU[odx].DrawText( pMode ) PUB MENUSetText( guid, pPtr ) | odx 'Place new text on the menu item. ' pPtr points to the text, it MUST be the same size (or less) as the text ' it is replacing odx := gz_elem[guid] & G_OMSK MENU[odx].SetText( pPtr ) PUB MENUSetStatus( guid, pStat ) | odx 'set a user defined status BYTE (any value fro 0 to 255) odx := gz_elem[guid] & G_OMSK MENU[odx].SetStatus( pStat ) PUB MENUGetStatus( guid ) | odx 'get the use defined status odx := gz_elem[guid] & G_OMSK return MENU[odx].GetStatus CON ''=====< INPUT FIELD INTERFACE FUNCTIONS >================================ PUB INPFInit(pRow, pCol, pWidth, pType, pTitlePtr ) | idx, gdx, retVal 'Creates an input field box with specified width and text. Something like: ' ----------------------- ' |Title| input field | ' ----------------------- ' ' pRow = row upper location ' pCol = col left location ' pWidth = width of the control in columns ' pType = 0 = standalone 1=tacked on to above ' pHeight = height of the control in rows ' pTitlePtr = title text ( remainder is used for the input field ) ' 'Returns -1 if there are no more free elements in the SPIN object array ' guid on success which is unique and used to identify the specific ' instance of the control. retVal := -1 repeat idx from 0 to GZ_INPF - 1 gdx := INPF[idx].get_gzidx if gz_elem[gdx] & G_INIT == 0 'is it free retVal := gdx gz_elem[gdx] |= G_INIT 'mark it used INPF[idx].Init( pRow, pCol, pWidth, pType, pTitlePtr, @scrn, VGACOLS ) quit return retVal PUB INPFIsIn( guid ) | odx ' returns true if the mouse is inside the input field ' false otherwise odx := gz_elem[guid] & G_OMSK return INPF[odx].IsIn( MOUS.bound_x, MOUS.bound_y ) PUB INPFClear( guid ) | odx 'clear the input field odx := gz_elem[guid] & G_OMSK INPF[odx].clear PUB INPFSelect( guid, pSel ) | odx 'pSel = 1 to select 0 to deselect -1 to toggle it odx := gz_elem[guid] & G_OMSK INPF[odx].Select( pSel, @cx1, @cy1 ) liveINPF := odx cm1 := %111 'turn text cursor on, underscore slow blink PUB INPFGetString( guid, pBuf ) | odx, tmp, str, len 'places the string in the input field into the buffer provided then clears 'the input field. odx := gz_elem[guid] & G_OMSK tmp := INPF[odx].GetStringCode str := ( tmp & $1FFF0000 ) >> 16 len := tmp & $000000FF bytemove( pBuf, @scrn.byte[str], len ) byte[pBuf][len] := 0 INPFClear( guid ) CON ''=====< STATUS LAMP INTERFACE FUNCTIONS >================================ PUB STATInit( pRow, pCol, pWidth, pTitlePtr ) | idx, gdx, retVal 'Creates a status lamp with specified width and text. Something like: ' ' Title : XXXX ' ' where XXXX is user supplied condition status ' ' pRow = row upper location ' pCol = col left location ' pWidth = width of the control in columns ' pHeight = height of the control in rows ' pTitlePtr = title text text (text must be 7 less than width ) ' 'Returns -1 if there are no more free elements in the SPIN object array ' guid on success which is unique and used to identify the specific ' instance of the control. retVal := -1 repeat idx from 0 to GZ_STAT - 1 gdx := STAT[idx].get_gzidx if gz_elem[gdx] & G_INIT == 0 'is it free retVal := gdx gz_elem[gdx] |= G_INIT 'mark it used STAT[idx].Init( pRow, pCol, pWidth, pTitlePtr, @scrn, VGACOLS ) quit return retVal PUB STATIsIn( guid ) | odx ' returns true if the mouse is inside the menu item ' false otherwise odx := gz_elem[guid] & G_OMSK return STAT[odx].IsIn( MOUS.bound_x, MOUS.bound_y ) PUB STATSet( guid, pSet, pStrPtr ) | odx 'pSet = 0 = off mode (uses normal video) ' 1 = on mode (uses inverted video) 'pStr = pointer to status string (4 chars max) odx := gz_elem[guid] & G_OMSK STAT[odx].Set( pSet, pStrPtr ) PUB STATGetStatus( guid ) | odx 'returns the current status of the object (1=on 0=off) odx := gz_elem[guid] & G_OMSK return STAT[odx].GetStatus CON ''===== START OF VGA HIGH RES TEXT SCREEN FUNCTIONS ====================== PUB PrintStr( prRow, prCol, strPtr, inv ) | strLen, vgaIdx, idx 'this places text anywhere on the screen and can overwrite UI elements ' ' prRow = row ' prCol = column ' strPtr = pointer to null terminated string ' inv = 0 for normal 1 for inverted video if ( prRow < VGAROWS ) AND ( prCol < VGACOLS ) strLen := strsize( strPtr ) vgaIdx := prRow * VGACOLS + prCol bytemove( @scrn.byte[vgaIdx], strPtr, strLen ) if inv repeat idx from 1 to strLen byte[@scrn][vgaIdx] += 128 vgaIdx++ PUB ClearScreen( ForeClr, BackClr ) | wdClr ' This clears the whole screen and sets all rows to the given colours ' ForeClr and BackClr are best represented as quaternary numbers (base 4) ' - these are represented as %%RGB where there are 4 levels for each ( R, G, B) ' - thus entering %%003 is brightest Green wdClr := BackClr << 10 + ForeClr << 2 LONGFILL( @scrn, $20202020, VGACOLS*VGAROWS/4 ) '4 space characters in long WORDFILL( @colors, wdClr, VGAROWS ) PUB SetLineColor( line, ForeClr, BackClr ) | wdClr ' This sets a single row to the given colours ' ForeClr and BackClr are best represented as quaternary numbers (base 4) ' - these are represented as %%RGB where there are 4 levels for each ( R, G, B) ' - thus entering %%003 is brightest Green if line < VGAROWS wdClr := BackClr << 10 + ForeClr << 2 colors[line] := wdClr {{ ┌────────────────────────────────────────────────────────────────────────────┐ │ TERMS OF USE: MIT License │ ├────────────────────────────────────────────────────────────────────────────┤ │Permission is hereby granted, free of charge, to any person obtaining a copy│ │of this software and associated documentation files (the "Software"), to │ │deal in the Software without restriction, including without limitation the │ │rights to use, copy, modify, merge, publish, distribute, sublicense, and/or │ │sell copies of the Software, and to permit persons to whom the Software is │ │furnished to do so, subject to the following conditions: │ │ │ │The above copyright notice and this permission notice shall be included in │ │all copies or substantial portions of the Software. │ │ │ │THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR │ │IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, │ │FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE │ │AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER │ │LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING │ │FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS│ │IN THE SOFTWARE. │ └────────────────────────────────────────────────────────────────────────────┘ }}