[ PowerBASIC Programmer's Guide ]

[ to find questionable areas,

try Control_QA, "**************"

I added this first section, and edited it to speak more to them directly,

as "you", and to a lower capability level. " I changed the

order of the sections. ]

-

Chapter 14

POPUP

(TERMINATE AND STAY RESIDENT) PROGRAMMING

Popup programs will save you time by being ready to use at the touch of a button. They can run in the background. They can help you prevent "out of memory" error messages, by letting you break up big huge programs into smaller pieces. And they can respond to interrupts.

PowerBASIC's popup programming mechanisms make it easy to create advanced Terminate and Stay Resident" (TSR) programs, without needing to buy extra software, or spending days exploring advanced technical reference manuals, trying to write it yourself.

Most of the tedious details are taken care of by PowerBASIC.

Built-in popup programming mechanisms give an average PowerBASIC programmer the ability to do things formerly done only by assembly language or "C" language programmers.

PowerBASIC gives you several different methods of controlling how these popup programs can be "popped up" to the foreground to run, and how they can be "popped down", to become dormant in the background until needed again.

PowerBASIC takes care of swapping these popup programs in and out.

All of this is built into PowerBASIC v3.0 and later.

Many details that have not yet been built into PowerBASIC are documented in this chapter on popup programming, and in the PowerBASIC Reference Guide.

To make it easier for you, sample source code utilizing the popup commands are included in the manual.

**************************and in the example code on the floppy???

If you need more help, that is not covered in these manuals, or in the examples, call PowerBASIC's technical support.

COMPATIBILITY

PowerBASIC popup programs are compatible with DOS v2.0 and above, and with most other TSR programs. Rules for writing your popup program so that it will be compatible are on page *********

USES OF POPUP PROGRAMS

POPUP KEY Ready to use at the touch of a button

With the POPUP KEY command, your program can be ready to use at the touch of a button. You will not need to remember a whole long filename to get it started.

When it gets finished, it pops down again, and your screen will look just like it did before you touched the hot key. You will be at the exact same place in your first program.

A POPUP KEY program that is already memory resident can be re-activated faster with a "hot key" than by loading it in from the disk drive each time. This will save you time.

Remarks

Once the POPUP KEY command is executed, the hot key chosen cannot be used for other features elsewhere in your software. It becomes installed at a level closer to the keyboard input itself, and can only be removed by uninstalling the popup program, or by temporarily disabling the popup activation checking. See POPUP KEY OFF, POPUP KEY ON.

POPUP TIMER Background, timer-controlled

Using POPUP TIMER to activate your popup program gives you "set and forget" timer-controlled capability, in the background.

Once a POPUP TIMER program is installed, it will stay loaded, dormant in the background. Every so often, it will "pop up" to the foreground to run for a few microseconds, then go back to sleep in the background, without you having to worry about it.

You can put your attention on the program that you are running in the foreground.

This is similar to multitasking. You can use a background level to do work that does not need operator attention, like printing pages.

The microprocessor speed is so fast, compared to your typing speed, that a background program can run without you even noticing it.

POPUP QUIET Timer-controlled activation

Using POPUP QUIET to activate your popup program also gives you "set and forget", timer-controlled capability, but instead of regular intervals like POPUP TIMER, a POPUP QUIET program will only be activated when the human operator does NOT use the computer for a while, when no keyboard or mouse activity occurs for a certain number of minutes.

The software timer will be reset to zero every time that you press a button on the keyboard or move your mouse.

This command can be used for a screen-saving program with an older style monitor. In some companies, it could be used to be sure that a particular class of worker is on duty, for instance, a security guard or a nuclear power plant operator.

If no one is typing into the keyboard, or moving the mouse, the computer program would assume that no one is "watching", and activate an alarm or call a telephone number, to tell a human being to come and see what is happening.

In an educational setting, it could be used to identify periods when the student needs some extra help in certain subject areas. In the same way, it could be used to identify times when a novice computer user, or a new user of your software, might need an extra level of help file.

POPUP INTERRUPT

Computer-controlled activation

Hardware or software interrupts

Using POPUP INTERRUPT as the method to activate your popup program gives you interrupt-driven computer-controlled activation. Once installed, they can be re-activated on demand, without you having to be there, by either software or hardware interrupts. This is also "set and forget" capability.

When POPUP INTERRUPT is used to service hardware interrupts, swapping may not be possible.

POPUP INTERRUPT uses a unique interrupt number for each popup program. Each POPUP INTERRUPT program works like a "private" telephone line. It does not have to ignore program calls that are not addressed to it, like programs using POPUP MULTIPLEX must do. Examples are programs operating a fax computer board, or a modem program.

POPUP MULTIPLEX

Computer-controlled activation

Software interrupts

Using POPUP MULTIPLEX to activate your popup program also gives you software interrupt-driven computer-controlled activation. Once installed, these programs can be re-activated on demand, by software interrupts. This is also "set and forget" capability.

POPUP MULTIPLEX uses the same interrupt number for each popup program attached to it, but also uses two register masks to identify which popup program is being called.

This works like a mailbox or extension number, and a personal identification number. Each POPUP MULTIPLEX program must check these two register masks and ignore all "party-line calls" except its own calls. It is possible to handle more popup programs with the same interrupt number, but response to time- critical functions like a COM port is not as fast as with POPUP INTERRUPT.

RELIEVE MEMORY SHORTAGES

Breaking your program up into smaller independent modules that interact with a mainline module, can mean that your program can keep on growing and becoming more complex, and yet not be limited by 640kb.

This can become important as you develop your software more and more. Adding more features, and more error-checking and error-recovery code, will eventually make your program grow too large for available RAM.

If you have been frustrated by the "Out of Memory" error message, as the reward for all your hard work, the POPUP MULTIPLEX and POPUP INTERRUPT program mechanisms may be the answer to your problem.

You can relieve the memory shortages by taking seldom-called chunks of source code out of your big program, and making them into independent popup programs.

These memory-resident smaller modules are sometimes called "overlay" programs. In popped-down, swapped-out status, these overlay programs can each use as little as 5kb of conventional RAM memory.

The remainder of their memory images are stored temporarily in EMS memory, or on a disk file.

Likely candidates for this conversion would be subroutines or functions, or groups of these, that are largely self-contained, and do not require a lot of variable passing.

Even programs that need a lot of variables to be passed as parameters can use other means, like saving important variables to a disk file, or swapping the data to a disk file, using BSAVE and BLOAD.

Making smaller faster program modules will make your programs more versatile and powerful.

ESSENTIAL STEPS

In invoking PowerBASIC's popup features:

To install a popup program,

Select the popup activation method.

Pop down.

When activated, it will

Pop up.

Perform some work.

Loop to pop down again

or

Uninstall.

POPPING DOWN

Popup Inactivation Methods

The user can choose from these methods of "popping down",

POPUP SLEEP USING EMS Uses EMS memory to swap

POPUP SLEEP USING FileName$ Uses a disk file to swap

POPUP SLEEP USING EMS, FileName$ Uses EMS memory or

a disk file to swap

POPUP SLEEP Becomes dormant without swapping

REMARKS

If you have enough EMS memory, POPUP SLEEP USING EMS is the fastest choice.

Before "popping down", the program needs to release extra memory that has been allocated by PowerBASIC, but has not used for the heap, or else there will be a lot of wasted EMS memory or disk space.

Use the SETMEM function, with a negative number larger than 640kb. PowerBASIC will try to release it all, but it will not cause an error if it is not an exact number.

dummy=SETMEM(-700000)

To reserve space for allocating dynamic arrays after it is popped up, use the SETMEM function, with a positive number equal to the number of bytes that will be needed, for instance, 8000 bytes.

dummy=SETMEM(8000)

When popping down again, after being activated,PowerBASIC will re-inactivate the popup program, using the same POPUP SLEEP method, and ignoring any USING options.

POPPING UP

Popup activation methods

The user can choose from these methods of "popping up",

POPUP KEY CHR$( RequiredShiftKeys, scancode (, OptionalShiftKeys) )

POPUP INTERRUPT InterruptNo%, timeout, ChainBefore, ChainAfter

POPUP MULTIPLEX AXmask, DXmask

POPUP QUIET Ticks

POPUP TIMER Ticks

UNINSTALLING

The popup program will be uninstalled by either of the two following

methods:

* Use of the END command

* Finishing execution of the popup program without looping to

pop down again

Techniques for signaling when a popup program should terminate and become uninstalled include passing it a pre-defined value in a register, or a special hot key from the operator.

Before any method of uninstalling should be performed, POPUP(1) should be checked, to see if it is safe to uninstall.

Example

rem false (busy) is zero

rem true (ready) is non-zero

SafeToUninstallFlag%=POPUP(1)

IF ISFALSE SafeToUninstallFlag% THEN

print"Unable to uninstall"

ELSE

print"Uninstalling"

END

END IF

On the command line

Xcommand$=UCASE$(command$)

if Xcommand$="OFF" then goto UninstallMe

Input a special character

PRINT "Type Q to uninstall, ENTER to resume sleep."

a$ = INPUT$(1) 'wait for key to cancel

IF UCASE$(A$)="Q" THEN

UninstallMe:

IF POPUP(1) THEN

dummy2$=FNKeepScreen$

LOCATE 12,20

PRINT " +-------------------------------------+" ;

LOCATE 13,20

PRINT " ¦ Uninstalling KEEPTIME ¦" ;

LOCATE 14,20

PRINT " ¦ ¦" ;

LOCATE 15,20

PRINT " ¦ ¦" ;

LOCATE 16,20

PRINT " +-------------------------------------+" ;

LOCATE 15,26

INPUT "ENTER TO CONTINUE ";X$

dummy$=FNRestoreScreen$ (dummy2$)

END 'this uninstalls us

END IF

REG 1, &HC001 : REG 4, 252 ' Alter AX,DX to show we were here

POPUP SLEEP ' before going to sleep

WEND

Pass it a special number

( POPUP INTERRUPT or POPUP MULTIPLEX )

DUMMY&=SETMEM(-70000) '...............................Allocate 1K of RAM

DUMMY&=SETMEM(+1024)

POPUP INTERRUPT &H99, 10, OFF, OFF '..........Popup on CALL INTERRUPT &H99

DO

POPUP SLEEP USING EMS '...............Swap to EMS and go to sleep

IF REG(1)=255 THEN '...................255 in REG(1) means END!

dummy=FNDeathKnell

ELSE '........................Here, we're popping up for some ACTION!

SELECT CASE REG(1) '.........REG(1) contains info from caller

CASE 0 '..........................popup help screens

:

CASE 1 '.........................popup a text editor

:

CASE 2 '......................popup a modem terminal

:

CASE 3 '.................Popup a disk-tree directory

:

END SELECT

END IF

input"Do you want to exit? ";x$: if x$="Y" then END

LOOP '...............................We terminate elsewhere. Do this forever

def FNDeathKnell

POPUP TIMER 18 '.......................Popup now every second

DO WHILE Seconds < 5 '.................Try this for 5 seconds

POPUP SLEEP '.............Allow caller to exit to DOS

IF POPUP(1) THEN '.................We can remove TSR!

PRINT "Tsr removed."

END '.....................End and free memory

END IF '............Otherwise, can't free memory yet!

INCR Seconds '................increment and try again

LOOP '.............................No use trying for too long

PRINT "Unable to remove TSR." '.....................Tisk Tisk

PRINT "4K left in memory." '.............We can't free the 4K

POPUP STUFF CHR$(13),0,0 '........To force another DOS prompt

END '.............................So just end and leave it be

end def

dummy=FNBiologicalClockOFF (InterruptNumber%)

def FNBiologicalClockOFF (InterruptNumber%)

rem Call the TSR for the last time and order it to die

REG 1, 255 ' destruct command

CALL INTERRUPT InterruptNumber%

PRINT "Program Ending"

END

end def

Extra Popup Commands

----------------------------------------------------------------

In some popup programs, you may want to simulate user input, for instance, to create a continuously running demo, for display in a store. The command POPUP STUFF can "stuff" the keyboard buffer and fool the keyboard driver program to make it appear that a person has typed these characters into the keyboard.

Another use might be a computer-based tutorial, like a demo, or a software testing process, with simulated input.

POPUP STUFF TextString$, InitialDelayTicks%, TicksBetweenChar%

This could be used to read in lines from a text file on the disk, and funnel these lines to the keyboard, like running a batch file.

The second parameter allows you to build in a pause before stuffing starts.

The third parameter allows you to build in a shorter wait in between each character, to make it appear to run slow enough for a person passing by to notice.

If you used it to "playback" commands from a disk text file, like in batch mode, you could set the second and third parameters to high numbers while you tested the program, then change them to 1 for faster execution.

USING SAMPLE PROGRAMS AS A TEMPLATE

rem cloned from ASCIITSR.BAS

$COMPILE EXE ' this tells PB to make a standalone EXE

$LIB IPRINT OFF ' allow graphic characters to print

dummy=FNSaveConditionsBeforeChangingThem

%AX=1: %DX=4

x& = SETMEM(-700000) ' release unused memory before sleep

PopupPgmName$="............" '

POPUP KEY CHR$(8,30,247) ' ALT A is the hot key

AXmask%=&HC000: DXmask%=254 ' installs itself with these masks

POPUP MULTIPLEX AXmask%, DXmask% ' reg AX and DX get this pattern as an ID

REG %AX, AXmask%

REG %DX, DXmask% ' check to see if installed already

CALL INTERRUPT &H2F ' do the multiplex interrrupt

IF REG(1)=&HC001 AND REG(4)=252 THEN

LOCATE 12,20

PRINT "+-------------------------------------+";

LOCATE 13,20

PRINT "¦ ";PopupPgmName$;" is already installed ¦";

LOCATE 14,20

PRINT "+-------------------------------------+";

END 'we were already installed

END IF

if len(PopupPgmName$)>8 then

SwapFile$ = LEFT$(CURDIR$,2)+"\"+left$(PopupPgmName$,8)+".SWP"

else

SwapFile$ = LEFT$(CURDIR$,2)+"\"+PopupPgmName$+".SWP"

end if

REG %AX, &HC001 ' Alter AX,DX to show we were here

REG %DX, 252 ' this protects against repetitive installations

dummy=FNRestoreConditionsBeforePoppingDownOrUninstalling

POPUP SLEEP USING EMS, SwapFile$ ' before going to sleep

WHILE 1=1

dummy=FNSaveConditionsBeforeChangingThem

' checking to see if this call is for us

IF REG(1)=AXmask% AND REG(4)=DXmask% THEN

' yes, it is ours

GOSUB YourProcedure

rem ...

rem ...

END IF

a$ = INPUT$(1) 'wait for key to cancel

dummy=FNRestoreConditionsBeforePoppingDownOrUninstalling

IF UCASE$(A$)="Q" THEN IF POPUP(1) THEN END 'this uninstalls us

REG %AX, &HC001

REG %DX, 252 ' Alter AX,DX to show we were here

POPUP SLEEP ' before going to sleep

WEND

YourProcedure:

rem ...

rem ...

RETURN

COMPATIBLITY WITH OTHER SOFTWARE

To be "well-behaved", and coexist compatibly with other modules or other vendors' software, your popup program should save initial conditions of the following system functions, before changing them, and then restore them before uninstalling or popping back down.

* default drive and subdirectory

Use CURDIR$ to save. Use CHDIR and CHDRIVE to restore conditions.

* screen mode

Use internal variables "pbvScrnMode" and "pbvScrnCols" to save conditions.

Use SCREEN and WIDTH to restore conditions.

* screen contents

Use PEEK$ or BSAVE to save the screen contents.

Use POKE$ or BLOAD to restore the screen contents.

PEEK$ and POKE$ will use RAM memory for storage.

BSAVE and BLOAD will use disk space for storage.

* cursor position

Use POS and CSRLIN to save cursor position.

Use LOCATE to restore saved cursor position.

* closing any open files

Use CLOSE.

----------------------------------------------------------------

Example functions, which may need further testing:

def FNSaveDefaultDriveAndSubdirectory$

CurrentDirectory$=CURDIR$

FNSaveDefaultDriveAndSubdirectory$=CurrentDirectory$

end def

def FNRestoreDefaultDriveAndSubdirectory$

print"CurrentDirectory$=";CurrentDirectory$

CHDRIVE left$(CurrentDirectory$,2)

CHDIR CurrentDirectory$

end def

def FNTestSaveAndRestoreDefaultDriveAndDirectory

CurrentDirectory$=FNSaveDefaultDriveAndSubdirectory$

print"Now at ";CURDIR$

CHDRIVE "E:"

CHDIR "\CALRES2"

print"Now changed to ";CURDIR$

dummy$=FNRestoreDefaultDriveAndSubdirectory$

print"Now changed back to ";CURDIR$

end def

def FNSwapOutScreenToString$

x% = POS : y% = CSRLIN

DEF SEG = &hB800

SaveScreen$ = PEEK$(0,4000) ' save the entire screen

FNSwapOutScreenToString$=SaveScreen$

end def

def FNRestoreScreenFromString$

DEF SEG = &hB800

POKE$ 0, SaveScreen$ : LOCATE y%, x% 'restore screen

SaveScreen$="": 'releases memory

end def

def FNSaveScreenMode%

rem Use internal variables "pbvScrnMode" and "pbvScrnCols" to save conditions.

rem documentation on this is found in the help files

SavedScreenMode%=pbvScrnMode

SavedScreenColumns%=pbvScrnCols

end def

def FNRestoreScreenMode%

SCREEN SavedScreenMode%

WIDTH "SCRN:", SavedScreenColumns%

end def

def FNSaveCursorPosition

BeforeX%=CSRLIN

BeforeY%=POS(0)

end def

def FNRestoreCursorPosition

LOCATE BeforeX%,BeforeY%,1

end def

def FNSaveConditionsBeforeChangingThem

CurrentDirectory$=FNSaveDefaultDriveAndSubdirectory$

BeforeScreenMode%=FNSaveScreenMode%

dummy=FNSaveCursorPosition

SaveScreen$=FNSwapOutScreenToString$

end def

def FNRestoreConditionsBeforePoppingDownOrUninstalling

dummy$=FNRestoreDefaultDriveAndSubdirectory$

dummy$=FNRestoreScreenFromString$

dummy$=FNRestoreScreenMode%

dummy=FNRestoreCursorPosition

end def

ORDER OF INSTALLING AS TSR

Popup programs installed using the POPUP MULTIPLEX interrupt are tried according to which are the newest, somewhat like a pushdown stack.

The checking of these register masks against the list of installed register mask values proceeds in reverse order, checking the newest installed one first, and then down the list to the longest installed program last.

A multiplex TSR can call another multiplex TSR only if the second one was loaded before it.

To call one multiplex TSR from another multiplex TSR, set the registers AX and DX with the correct values, and issue a CALL INTERRUPT &H2F.

The correct values for these registers are like a mailbox or extension number, and the password PIN that goes with it, or like needing two keys to get into your safety deposit box, yours and the one the bank keeps.

METHODS OF PASSING PARAMETERS

BETWEEN POPUP PROGRAMS

When calling a popup program, with POPUP INTERRUPT or POPUP MULTIPLEX,

you can pass parameters to it thru the registers.

POPUP MULTIPLEX can return values in the registers, when it completes, or pops back down.

POPUP INTERRUPT restores the registers to the values it saved at the beginning of its execution, so it cannot return values using the registers.

CAUTIONS

Do not try to swap in and out a program with an open COM line.

Interrupt-driven popup programs may not use SHELL, or any other form of call to

MS-DOS, because MS-DOS is not re-entrant.

See MS-DOS Developer's Guide, page 130-131

CHOOSING THE INTERRUPT NUMBER

FOR POPUP INTERRUPT

Various sources of information will tell you which system interrupts are available for users. The program ASQ, that comes with 386MAX, by Qualitas, tells us that the following interrupts are available on an 80386.

Interrupt Title # Name

ROM BASIC &H18

User Interrupt &H60 thru &H66 None

Not used &H78 thru &H7F None

Reserved by BASIC &H80 thru &H85 None

Used by BASIC &H86 thru &HE7 None

Used by BASIC &HE8 thru &HE9 -Available-

Used by BASIC &HEF -Available-

Not used &HF9 None

Not used &HFA -Available-

Not used &HFB -Available-

Not used &HFE -Available-

PowerBASIC Reference Guide, page 252, tells us that PowerBASIC uses interrupts &H08, &H09, &H10, &H13, &H17, &H21, &H28, and &H2F.

Your popup programs can probably use any interrupt number that is normally marked as "Reserved for BASIC", or "Used by BASIC", except the ones explicitly reserved for use by PowerBASIC, mentioned above.

Qualitas has released a shareware version of ASQ.

Disclaimer

Since each person's PC has its own unique configuration, as well as its own unique set of drivers, TSR's, and programs, no absolutely certain list of interrupt numbers that are safe to use, can be reliably defined for everyone, and printed in a book.

This file has been created with the evaluation or unregistered copy of
EasyHelp from Eon Solutions
(Tel: UK 0973 209667, Email: eon@cix.compulink.co.uk)