Features of Dandee Menu V1.04 1. Uses very little memory, takes about 160 bytes. 2. Is Multi-User - some others are, some aren't, some only work with selected networks. 3. Not a lot of Money 4. No Royalties or any of that crap. 5. Does not use Graphics - some terminals on multi-user systems dislike anything other then pure text mode. 7. Can be maintained by the end user. 8. Calculator - Calendar - Events When Menu starts up it will check to see if any events are scheduled and if so, will go to a reminder screen,with ringer. 9. Alt E will pop up the event screen at any time, with a ringer for today's events. 10. Alt D will pop up a calendar, with access to the event scheduler 11. Alt C will pop up a calculator. 12. Alt R will execute dos commands 13. User definable parameters for Screen Blanking 14. Passwords for Options - Menu Changes - Exit to Dos Default Password is PASS all caps 15. PassWords for individual menu selections 16. Returns to Last Menu after execution 17. Variable paths for MenuFile - Mentitle - Dates - DDmenu.bat 18. Screen Saver Installation: Install it in any subdir you desire, it uses no path, looks where it is, or in the variable path setup. When you run it for the first time, you can setup your program drives and paths. The system relies on a batch file named DDMENU.BAT. If it is missing, type DANDEE and the program will create it for you. Other batch files A.BAT thru P.BAT and AA.BAT thru XX.BAT will be created as needed. Include the location of DDmenu.bat in your system Path so it can be found form any directory/Drive location. Your path may look like this in autoexec.bat Path=c:\dos;c:\windows;c:\menu  DDmenu.Bat may reside in c:\menu To Run, just type DDmenu If it is missing just Dandee There is on-line help using F1 that will explain how to set up your menu's. !! Multi User Systems !! Multi-User systems have a problem sharing batch files, so now you can put a copy of Dandee.exe - Control.Dat - D_rec.Dat - Pass.dat in a unique directory for each user, and the program will will either create the batch files A thru XX as needed, or you can copy a master set to each users directory. You can also share the same Menufile, Menu Titles, and Dates(Events) by setting the pathname variable to the directory where the files reside, or you can create new ones for each user, or copy in a master set to their directory, and customize them. To set the pathname variable for the above mentioned files, press ALT O from the Page 1 Menu screen. Example of variable paths. IMPORTANT NOTE: Include the location of ddmenu.bat in the user's path ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ Contains - Menufile.* Mentitle.* Dates.* Pass.*³ \Menu ÄÄÄÄÄÄÄÄÄÄÄÄÄ´ *.Hlp and all the master *.bat *.exe Etc. ³ ³ ³ The Console might use this directory ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ³ This directory may only contain Dandee.exe, Pass.Dat ³ \User1 ÄÄÄÄÄÄÄÄÄÄÄÄ´ Control.Dat d_rec.Dat Dandee.Hlp and all the ³ ³ ³ master *.bat files. This the user would be using ³ ³ ³ all the menu defs form \menu. DDmenu.Bat can also ³ ³ ³ be here, but will be created if it doesn't exit. ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ ³ User 2 may be someone with very low access so ³ \User2 ³ would only copy Dandee.Exe, D_rec.Dat, *.hlp Pass.dat ³ ³ and Control.dat to their directory. Make sure the ³ ³ Variable path is set to nothing, and all the *.bat ³ ³ MenuFile.*, MenTitle.* and dates.* wil be created ³ ³ automatically. You could also copy in the master ³ ³ set and Edit them accordingly. You could also ³ ³ point the menu title file to \menu and the ³ ³ menufile to nothing, this would show all the ³ ³ standard menu titles, but not the menu selections. ³ ³ ³ ³ There are many more combinations. ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ There is on-line help using F1 that will explain how to set up your menu's. This is a live program, use it as you like. If you want to become registered user. Send $15.00 Check or Money Order to: Dan Scott 8 Applewood Dr Ballston Lake, NY 12019 Include your name, address, phone and your Company Name if applicable. Registered Version: Will allow you to change the Licensed To: Name, and also the Distributed By information on the intro screen will show your company information. There are no limitations or royalties or anything, distribute as many copies as you like. You can get the latest updates from my BBS free for 1 year. If you have any problems, give me a call (518) 899-2033 or on CIM Clarion forum Daniel K. Scott 74170,1201 Have Fun !! Dandee Menu, and associated programs & documentation are hereby released as SHAREWARE. This gives you the right to use the software for your evaluation purposes. Sale or Inclusion with commercial or distributed software is not allowed as evaluation. If you continue to use Dandee Menu please consider the remitance of the software registration fee and register the software. NOTICE: This software has NO WARRANTY, either express or implied. Use it at your own risk. Disclaimer ÄÄÄÄÄÄÄÄÄÄÄÄ Dan Scott, makes no warranties, either express or implied, including the implied warranties of fitness for a particular purpose or mechantability, and Dan Scott shall not be liable for tort, indirect, special or consequential damages such as loss of profits or loss of good will from the use or inability to use the software for any purpose. I have included the file defs for Dates.* in case you want to interface the Date file with some of your programs. I have also included the code for Ent_dates and Upd_dates in case you want to access the Dates file within your programs. !! Dates Files (events are stored here) DATES FILE,name('dates'),PRE(DAT),CREATE,RECLAIM DATE_KEY KEY(DAT:DATE),DUP,NOCASE MD_KEY KEY(DAT:MNTHDAY),DUP,NOCASE ! keyed on month and day NOTES MEMO(400) RECORD RECORD DATE LONG EVENT STRING(30) ! desc of event DURATION STRING(1) ! Always or Onetime TIME STRING(5) ! Human Time Entry @p##-##p LTIME LONG ! Clarion Time @d1 AP STRING(2) ! am/pm TESTDAYS LONG ! Used to see if event should be displayed MNTHDAY LONG ! Month(today()) & day(today()) . . GROUP,OVER(DAT:NOTES) ! notes about the event DAT_MEMO_ROW STRING(40),DIM(10) . !!! --- Included Code for dates Access ------ !!! !! ---------------- Update the date file ---------------!! MEMBER() UPD_DATES PROCEDURE Screen SCREEN WINDOW(22,44),AT(3,18),PRE(Scr),HUE(15,4) ROW(2,2) PAINT(9,42),HUE(15,1) ROW(22,2) PAINT(1,42),HUE(0,7) ROW(11,4) PAINT(1,4),HUE(14,0) ROW(3,3) PAINT(7,8),HUE(14,1) ROW(9,17) PAINT(1,17),HUE(14,1) ROW(7,15) PAINT(1,14),HUE(14,1) ROW(3,22) PAINT(1,5),HUE(14,1) ROW(3,37) PAINT(1,5),HUE(14,1) ROW(11,43) PAINT(10,1),HUE(15,1) ROW(21,1) PAINT(1,1),HUE(15,1) ROW(11,2) PAINT(10,1),HUE(15,1) ROW(11,3) PAINT(1,1),HUE(0,7) ROW(21,2) PAINT(1,42),HUE(14,1) ROW(1,1) STRING('ÚÄ{42}'),HUE(8,1) ROW(2,1) REPEAT(20);STRING('³'),HUE(8,1) . ROW(22,1) STRING('À'),HUE(8,1) ROW(1,44) STRING('¿'),HUE(15,1) ROW(2,44) REPEAT(20);STRING('³'),HUE(15,1) . ROW(22,2) STRING('Ä{42}Ù'),HUE(15,1) ROW(3,3) STRING('Date') ROW(5,3) STRING('Event') ROW(7,3) STRING('Keep') ROW(9,3) STRING('Remind') COL(10) STRING('m'),HUE(14,1) COL(11) STRING('e'),HUE(14,1) COL(17) STRING('days before event') ROW(11,2) STRING('N'),HUE(15,1) ROW(13,2) STRING('O'),HUE(15,1) ROW(15,2) STRING('T'),HUE(15,1) ROW(17,2) STRING('E'),HUE(15,1) ROW(19,2) STRING('S'),HUE(15,1) MESSAGE ROW(2,8) STRING(30),ENH date ROW(6,8) STRING(@D1),HUE(1,1) STIME COL(34) STRING(@T3),HUE(1,1) COL(41) ENTRY,USE(?First_Field) ROW(3,11) STRING(':') COL(12) ENTRY(@D1),USE(DAT:DATE),HLP('DATEH'),INS COL(22) STRING('Time:') COL(28) ENTRY(@p##:##p),USE(DAT:TIME),HLP('TIM'),SEL(14,4),OVR COL(34) MENU(@S2),USE(DAT:AP),SEL(14,4) COL(37) STRING('AM') COL(40) STRING('PM') . ROW(5,11) STRING(':') COL(12) ENTRY(@S30),USE(DAT:EVENT),HLP('EVENT'),OVR,UPR ROW(7,11) STRING(':') COL(12) MENU(@S1),USE(DAT:DURATION),HLP('DUR') COL(15) STRING('Always'),SEL(14,4) COL(22) STRING('OneTime'),SEL(14,4) . ROW(9,12) STRING(' '),HUE(15,1) COL(13) ENTRY(@N3),USE(DAT:TESTDAYS),HLP('TEST'),INS ROW(11,3) TEXT(10,40),USE(DAT:NOTES),HLP('NOTE'),SEL(1,7),OVR,LFT,UPR ROW(21,8) PAUSE('ESCAPE to ReDo - ENTER to Record'),USE(?PAUSE_FIELD),HUE(26,1) ROW(22,40) ENTRY,USE(?Last_Field) ROW(22,40) ENTRY,USE(?delete_Field) COL(40) PAUSE(''),USE(?Pause) . TABLE TABLE,PRE(SAV) SAVE_RECORD GROUP;BYTE,DIM(SIZE(DAT:RECORD)). SAVE_MEMO GROUP;BYTE,DIM(SIZE(DAT:NOTES)). . EJECT CODE OPEN(SCREEN) !OPEN THE SCREEN SETCURSOR !TURN OFF ANY CURSOR SAVE_RECORD = DAT:RECORD !SAVE THE ORIGINAL SAVE_MEMO = DAT:NOTES !SAVE THE ORIGINAL ADD(TABLE,1) !STORE IN MEMORY TABLE IF ACTION = 5 !AUTONUMBER ACTION DISK_ACTN# = 2 ! SET FOR PHYSICAL ACTION ACTION = 1 ! SET FOR LOGICAL ACTION ELSE !OTHERWISE DISK_ACTN# = ACTION ! SET ACTION FOR DISK WRITE . DISPLAY !DISPLAY THE FIELDS EXECUTE DISK_ACTN# !SET THE CURRENT RECORD POINTER POINTER# = 0 ! NO RECORD FOR ADD POINTER# = POINTER(DATES) ! CURRENT RECORD FOR CHANGE POINTER# = POINTER(DATES) ! CURRENT RECORD FOR CHANGE . ACTION# = ACTION !STORE REQUIRED ACTION LOOP !LOOP THRU ALL THE FIELDS MEM:MESSAGE = CENTER(MEM:MESSAGE) !DISPLAY ACTION MESSAGE DO CALCFIELDS !CALCULATE DISPLAY FIELDS ALERT !RESET ALERTED KEYS ALERT(ACCEPT_KEY) !ALERT SCREEN ACCEPT KEY ALERT(REJECT_KEY) !ALERT SCREEN REJECT KEY ACCEPT !READ A FIELD IF KEYCODE() = REJECT_KEY THEN BREAK. !RETURN ON SCREEN REJECT KEY EXECUTE ACTION !SET MESSAGE MEM:MESSAGE = 'Record will be Added' ! MEM:MESSAGE = 'Record will be Changed' ! MEM:MESSAGE = 'Press Enter to Delete' ! . IF KEYCODE() = ACCEPT_KEY !ON SCREEN ACCEPT KEY UPDATE ! MOVE ALL FIELDS FROM SCREEN SELECT(?) ! START WITH CURRENT FIELD SELECT ! EDIT ALL FIELDS CYCLE ! GO TO TOP OF LOOP . CASE FIELD() !JUMP TO FIELD EDIT ROUTINE OF ?FIRST_FIELD !FROM THE FIRST FIELD IF KEYCODE() = ESC_KEY THEN BREAK. ! RETURN ON ESC KEY IF ACTION = 3 THEN SELECT(?DELETE_FIELD).! OR CONFIRM FOR DELETE OF ?DAT:TIME if keycode()=accept_key then select(?+1). OF ?DAT:AP scr:stime = dat:time&dat:ap;if dat:time > 1 then dat:ltime=scr:stime else dat:ltime=0;dat:ap=''. OF ?PAUSE_FIELD !ON PAUSE FIELD IF KEYCODE() <> ENTER_KEY| !IF NOT ENTER KEY AND KEYCODE() <> ACCEPT_KEY| !AND NOT CTRL-ENTER KEY AND KEYCODE() <> 0 !AND NOT NONSTOP MODE BEEP ! SOUND KEYBOARD ALARM SELECT(?PAUSE_FIELD) ! AND STAY ON PAUSE FIELD . OF ?LAST_FIELD !FROM THE LAST FIELD IF KEYCODE() = 0 !IF IN AUTO SELECT MODE DO CALCFIELDS ! DO CALCULATIONS SELECT(?) ! TURN IT OFF . IF ACTION = 2 OR ACTION = 3 !IF UPDATING RECORD SAVE_RECORD = DAT:RECORD ! SAVE CURRENT CHANGES SAVE_MEMO = DAT:NOTES ! SAVE CURRENT CHANGES ADD(TABLE,2) ! STORE IN MEMORY TABLE GET(TABLE,1) ! RETRIEVE ORIGINAL RECORD HOLD(DATES,.10) ! TRY TO HOLD FILE GET(DATES,POINTER#) ! RE-READ SAME RECORD IF ERRORCODE() = 43 ! IF RECORD WAS ALREADY HELD RECOVER(120) ! ARM RECOVER HOLD(DATES) ! HOLD FILE GET(DATES,POINTER#) ! RE-READ SAME RECORD RECOVER() ! DISARM RECOVER . IF ERRORCODE() = 35 ! IF RECORD WAS DELETED IF DISK_ACTN# = 2 ! IF TRYING TO UPDATE DISK_ACTN# = 1 ! THEN ADD IT BACK ELSE ! RELEASE(DATES) ! RELEASE FILE ACTION = 0 ! TURN OFF ACTION . ELSIF | !OTHERWISE DAT:NOTES <> SAVE_MEMO OR | ! IF IT HAS BEEN CHANGED DAT:RECORD <> SAVE_RECORD ! BY ANOTHER STATION MEM:MESSAGE = 'CHANGED BY ANOTHER STATION' !INFORM USER SELECT(2) ! GO BACK TO TOP OF FORM BEEP ! SOUND ALARM RELEASE(DATES) ! RELEASE FILE SAVE_RECORD = DAT:RECORD ! SAVE RECORD SAVE_MEMO = DAT:NOTES ! SAVE MEMO DISPLAY ! DISPLAY THE FIELDS PUT(TABLE) ! FREE SAVED CHANGES CYCLE ! AND CONTINUE . GET(TABLE,2) ! READ CURRENT (CHANGED) REC DAT:RECORD = SAVE_RECORD ! MOVE RECORD DAT:NOTES = SAVE_MEMO ! MOVE MEMO DELETE(TABLE) ! DELETE MEMORY TABLE ITEM . EXECUTE DISK_ACTN# ! UPDATE THE FILE ADD(DATES) ! ADD NEW RECORD PUT(DATES) ! CHANGE EXISTING RECORD DELETE(DATES) ! DELETE EXISTING RECORD . IF ERRORCODE() = 40 ! DUPLICATE KEY ERROR MEM:MESSAGE = ERROR() ! DISPLAY ERR MESSAGE SELECT(2) ! POSITION TO TOP OF FORM IF ACTION = 2 THEN RELEASE(DATES). ! RELEASE HELD RECORD CYCLE ! GET OUT OF EDIT LOOP ELSIF ERROR() ! CHECK FOR UNEXPECTED ERROR EXECUTE ACTION ! BUILD AN ERROR MESSAGE ERROR" = 'Error: ' & ERROR() & ' ' | ! FOR ADDING & 'Adding to DATES' ERROR" = 'Error: ' & ERROR() & ' ' | ! FOR CHANGE & 'Changing DATES' ERROR" = 'Error: ' & ERROR() & ' ' | ! FOR DELETING & 'Deleting from DATES' . STOP(ERROR") ! HALT EXECUTION . IF ACTION = 1 THEN POINTER# = POINTER(DATES). !POINT TO RECORD SAVE_RECORD = DAT:RECORD ! NEW ORIGINAL SAVE_MEMO = DAT:NOTES ! NEW ORIGINAL ACTION = ACTION# ! RETRIEVE ORIGINAL OPERATION ACTION = 0 ! SET ACTION TO COMPLETE BREAK ! AND RETURN TO CALLER OF ?DELETE_FIELD !FROM THE DELETE FIELD IF KEYCODE() = ENTER_KEY | ! ON ENTER KEY OR KEYCODE() = ACCEPT_KEY ! OR CTRL-ENTER KEY SELECT(?LAST_FIELD) ! DELETE THE RECORD ELSE ! OTHERWISE BEEP ! BEEP AND ASK AGAIN . . . FREE(TABLE) ! RELEASE MEMORY TABLE RETURN ! AND RETURN TO CALLER CALCFIELDS ROUTINE IF FIELD() > ?FIRST_FIELD !BEYOND FIRST_FIELD? IF KEYCODE() = 0 AND SELECTED() > FIELD() THEN EXIT. !GET OUT IF NOT NONSTOP . SCR:MESSAGE = MEM:MESSAGE SCR:DATE = dat:date;dat:mnthday=sub(scr:date,1,2)&sub(scr:date,4,2) SCR:STIME = dat:time&dat:ap;if dat:time > 1 then dat:ltime=scr:stime. DAT:LTIME = SCR:STIME !! --------End of Upd_dates-------!! !! --------------- Date Table -----------------!! MEMBER() ENT_DATES PROCEDURE SCREEN SCREEN WINDOW(21,57),AT(2,11),PRE(SCR),HLP('ENTDATES'),HUE(0,3) ROW(6,4) PAINT(13,51),HUE(0,7) ROW(6,9) PAINT(1,5),HUE(1,7) ROW(1,1) STRING('ÚÄ{55}'),ENH ROW(2,1) REPEAT(19);STRING('³'),ENH . ROW(21,1) STRING('À'),ENH ROW(1,57) STRING('¿'),HUE(15,3) ROW(2,57) REPEAT(19);STRING('³'),HUE(15,3) . ROW(21,2) STRING('Ä{55}Ù'),HUE(15,3) ROW(5,3) STRING('ÚÄ{51}'),HUE(8,7) ROW(6,3) REPEAT(13);STRING('³'),HUE(8,7) . ROW(19,3) STRING('À'),HUE(8,7) ROW(5,55) STRING('¿'),HUE(15,7) ROW(6,55) REPEAT(13);STRING('³'),HUE(15,7) . ROW(19,4) STRING('Ä{51}Ù'),HUE(15,7) ROW(2,3) STRING('Locate By MM/DD:') ROW(4,7) STRING('Date Time Event') COL(41) STRING(' F1 - '),HUE(1,3) COL(49) STRING('Help'),HUE(4,3) ROW(20,6) STRING('INS'),HUE(4,3) COL(10) STRING('Add'),HUE(1,3) COL(17) STRING('ENTER'),HUE(4,3) COL(23) STRING('Select'),HUE(1,3) COL(33) STRING('DEL'),HUE(4,3) COL(36) STRING(' Delete '),HUE(1,3) COL(46) STRING('ESC'),HUE(4,3) COL(50) STRING('Exit'),HUE(1,3) LOCATOR ROW(2,20) STRING(4) COL(24) ENTRY,USE(?FIRST_FIELD) COL(24) ENTRY,USE(?PRE_POINT) REPEAT(13),INDEX(Ndx) ROW(6,4) POINT(1,50),USE(?POINT),ESC(?-1),SEL(11,4) DATE COL(7) STRING(@p##-##p) L2 COL(12) STRING(1),HUE(8,7) TIME COL(13) STRING(7),HUE(4,7) L3 COL(20) STRING(1),HUE(8,7) EVENT COL(21) STRING(30),HUE(14,7) . . NDX BYTE !REPEAT INDEX FOR POINT AREA ROW BYTE !ACTUAL ROW OF SCROLL AREA COL BYTE !ACTUAL COLUMN OF SCROLL AREA COUNT BYTE(13) !NUMBER OF ITEMS TO SCROLL ROWS BYTE(13) !NUMBER OF ROWS TO SCROLL COLS BYTE(50) !NUMBER OF COLUMNS TO SCROLL FOUND BYTE !RECORD FOUND FLAG NEWPTR LONG !POINTER TO NEW RECORD TABLE TABLE,PRE(TBL) !TABLE OF RECORD DATA PTR LONG ! POINTER TO FILE RECORD DATE STRING(@p##-##p) L2 STRING(@s1) TIME STRING(@s7) L3 STRING(@s1) EVENT STRING(30) MNTHDAY LONG . EJECT CODE ACTION# = ACTION !SAVE ACTION OPEN(SCREEN) !OPEN THE SCREEN SETCURSOR !TURN OFF ANY CURSOR TBL:PTR = 1 !START AT TABLE ENTRY NDX = 1 !PUT SELECTOR BAR ON TOP ITEM ROW = ROW(?POINT) !REMEMBER TOP ROW AND COL = COL(?POINT) !LEFT COLUMN OF SCROLL AREA RECORDS# = TRUE !INITIALIZE RECORDS FLAG IF ACTION = 4 ! TABLE LOOKUP REQUEST NEWPTR = POINTER(DATES) ! SET POINTER TO RECORD IF NOT NEWPTR ! RECORD NOT PASSED TO TABLE SET(DAT:MD_KEY,DAT:MD_KEY) ! POSITION TO CLOSEST RECORD NEXT(DATES) ! READ RECORD NEWPTR = POINTER(DATES) ! SET POINTER . DO FIND_RECORD ! POSITION FILE ELSE NDX = 1 ! PUT SELECTOR BAR ON TOP ITEM DO FIRST_PAGE ! BUILD MEMORY TABLE OF KEYS . RECORDS# = TRUE ! ASSUME THERE ARE RECORDS LOOP !LOOP UNTIL USER EXITS ACTION = ACTION# !RESTORE ACTION ALERT !RESET ALERTED KEYS ALERT(REJECT_KEY) !ALERT SCREEN REJECT KEY ALERT(ACCEPT_KEY) !ALERT SCREEN ACCEPT KEY ACCEPT !READ A FIELD IF KEYCODE() = REJECT_KEY THEN BREAK. !RETURN ON SCREEN REJECT KEY IF KEYCODE() = ACCEPT_KEY | !ON SCREEN ACCEPT KEY AND FIELD() <> ?POINT !BUT NOT ON THE POINT FIELD UPDATE ! MOVE ALL FIELDS FROM SCREEN SELECT(?) ! START WITH CURRENT FIELD SELECT ! EDIT ALL FIELDS CYCLE ! GO TO TOP OF LOOP . CASE FIELD() !JUMP TO FIELD EDIT ROUTINE OF ?FIRST_FIELD !FROM THE FIRST FIELD IF KEYCODE() = ESC_KEY | ! RETURN ON ESC KEY OR RECORDS# = FALSE ! OR NO RECORDS BREAK ! EXIT PROGRAM . OF ?PRE_POINT !PRE POINT FIELD CONDITION IF KEYCODE() = ESC_KEY ! BACKING UP? SELECT(?-1) ! SELECT PREVIOUS FIELD ELSE ! GOING FORWARD SELECT(?POINT) ! SELECT MENU FIELD . IF KEYCODE() = ESC_KEY ! BACKING UP? SCR:LOCATOR = '' ! CLEAR LOCATOR SETCURSOR ! AND TURN CURSOR OFF ELSE ! GOING FORWARD LEN# = 0 ! RESET TO START OF LOCATOR SETCURSOR(ROW(SCR:LOCATOR),COL(SCR:LOCATOR)) ! AND TURN CURSOR ON . OF ?POINT !PROCESS THE POINT FIELD IF RECORDS(TABLE) = 0 !IF THERE ARE NO RECORDS CLEAR(DAT:RECORD) ! CLEAR RECORD AREA UPDATE ! UPDATE ALL FIELDS ACTION = 1 ! SET ACTION TO ADD GET(DATES,0) ! CLEAR PENDING RECORD UPD_DATES ! CALL FORM FOR NEW RECORD NEWPTR = POINTER(DATES) ! SET POINTER TO NEW RECORD DO FIRST_PAGE ! DISPLAY THE FIRST PAGE IF RECORDS(TABLE) = 0 ! IF THERE AREN'T ANY RECORDS RECORDS# = FALSE ! INDICATE NO RECORDS SELECT(?PRE_POINT-1) ! SELECT THE PRIOR FIELD . CYCLE ! AND LOOP AGAIN . IF KEYCODE() > 31 | !THE DISPLAYABLE CHARACTERS AND KEYCODE() < 255 !ARE USED TO LOCATE RECORDS IF LEN# < SIZE(SCR:LOCATOR) ! IF THERE IS ROOM LEFT SCR:LOCATOR = SUB(SCR:LOCATOR,1,LEN#) & CHR(KEYCODE()) LEN# += 1 ! INCREMENT THE LENGTH . ELSIF KEYCODE() = BS_KEY !BACKSPACE UNTYPES A CHARACTER IF LEN# > 0 ! IF THERE ARE CHARACTERS LEFT LEN# -= 1 ! DECREMENT THE LENGTH SCR:LOCATOR = SUB(SCR:LOCATOR,1,LEN#) ! ERASE THE LAST CHARACTER . ELSE !FOR ANY OTHER CHARACTER LEN# = 0 ! ZERO THE LENGTH SCR:LOCATOR = '' ! ERASE THE LOCATOR FIELD . SETCURSOR(ROW(SCR:LOCATOR),COL(SCR:LOCATOR)+LEN#) !AND RESET THE CURSOR DAT:MNTHDAY = CLIP(SCR:LOCATOR) ! UPDATE THE KEY FIELD TIME# = CLOCK() !SAVE THE TIME LOOP UNTIL KEYBOARD() !WAIT FOR A KEYSTROKE IF CLOCK() > TIME# + 50 THEN BREAK. ! BUT ONLY 1/2 OF A SECOND . IF KEYBOARD() > 31 | !THE DISPLAYABLE CHARACTERS AND KEYBOARD() < 255 | !ARE USED TO LOCATE RECORDS OR KEYBOARD() = BS_KEY !INCLUDE BACKSPACE CYCLE . IF LEN# > 0 !ON A LOCATOR REQUEST DAT:MNTHDAY = CLIP(SCR:LOCATOR) ! UPDATE THE KEY FIELD SET(DAT:MD_KEY,DAT:MD_KEY) ! POINT TO NEW RECORD NEXT(DATES) ! READ A RECORD IF (EOF(DATES) AND ERROR()) ! IF EOF IS REACHED SET(DAT:MD_KEY) ! SET TO FIRST RECORD PREVIOUS(DATES) ! READ THE LAST RECORD . NEWPTR = POINTER(DATES) ! SET NEW RECORD POINTER SKIP(DATES,-1) ! BACK UP TO FIRST RECORD FREE(TABLE) ! CLEAR THE TABLE DO NEXT_PAGE ! AND DISPLAY A NEW PAGE . CASE KEYCODE() !PROCESS THE KEYSTROKE OF INS_KEY !INS KEY CLEAR(DAT:RECORD) ! CLEAR RECORD AREA ACTION = 1 ! SET ACTION TO ADD GET(DATES,0) ! CLEAR PENDING RECORD UPD_DATES ! CALL FORM FOR NEW RECORD IF ~ACTION ! IF RECORD WAS ADDED NEWPTR = POINTER(DATES) ! SET POINTER TO NEW RECORD DO FIND_RECORD ! POSITION IN FILE . OF ENTER_KEY !ENTER KEY OROF ACCEPT_KEY !CTRL-ENTER KEY DO GET_RECORD ! GET THE SELECTED RECORD IF ACTION = 4 AND KEYCODE() = ENTER_KEY! IF THIS IS A LOOKUP REQUEST ACTION = 0 ! SET ACTION TO COMPLETE BREAK ! AND RETURN TO CALLER . IF ~ERROR() ! IF RECORD IS STILL THERE ACTION = 2 ! SET ACTION TO CHANGE UPD_DATES ! CALL FORM TO CHANGE REC IF ACTION ! IF SUCCESSFUL RE-DISPLAY ACTN# = 0 THEN CYCLE. . NEWPTR = POINTER(DATES) ! SET POINTER TO NEW RECORD DO FIND_RECORD ! POSITION IN FILE OF DEL_KEY !DEL KEY DO GET_RECORD ! READ THE SELECTED RECORD IF ~ERROR() ! IF RECORD IS STILL THERE ACTION = 3 ! SET ACTION TO DELETE UPD_DATES ! CALL FORM TO DELETE IF ~ACTION ! IF SUCCESSFUL N# = NDX ! SAVE POINT INDEX DO SAME_PAGE ! RE-DISPLAY NDX = N# ! RESTORE POINT INDEX . . OF DOWN_KEY !DOWN ARROW KEY DO SET_NEXT ! POINT TO NEXT RECORD DO FILL_NEXT ! FILL A TABLE ENTRY IF FOUND ! FOUND A NEW RECORD SCROLL(ROW,COL,ROWS,COLS,ROWS(?POINT)) ! SCROLL THE SCREEN UP GET(TABLE,RECORDS(TABLE)) ! GET RECORD FROM TABLE DO FILL_SCREEN ! DISPLAY ON SCREEN . OF PGDN_KEY !PAGE DOWN KEY DO SET_NEXT ! POINT TO NEXT RECORD DO NEXT_PAGE ! DISPLAY THE NEXT PAGE OF CTRL_PGDN !CTRL-PAGE DOWN KEY DO LAST_PAGE ! DISPLAY THE LAST PAGE NDX = RECORDS(TABLE) ! POSITION POINT BAR OF UP_KEY !UP ARROW KEY DO SET_PREV ! POINT TO PREVIOUS RECORD DO FILL_PREV ! FILL A TABLE ENTRY IF FOUND ! FOUND A NEW RECORD SCROLL(ROW,COL,ROWS,COLS,-(ROWS(?POINT)))! SCROLL THE SCREEN DOWN GET(TABLE,1) ! GET RECORD FROM TABLE DO FILL_SCREEN ! DISPLAY ON SCREEN . OF PGUP_KEY !PAGE UP KEY DO SET_PREV ! POINT TO PREVIOUS RECORD DO PREV_PAGE ! DISPLAY THE PREVIOUS PAGE OF CTRL_PGUP !CTRL-PAGE UP DO FIRST_PAGE ! DISPLAY THE FIRST PAGE NDX = 1 ! POSITION POINT BAR . . . FREE(TABLE) !FREE MEMORY TABLE RETURN !AND RETURN TO CALLER SAME_PAGE ROUTINE !DISPLAY THE SAME PAGE GET(TABLE,1) ! GET THE FIRST TABLE ENTRY DO FILL_RECORD ! FILL IN THE RECORD SET(DAT:MD_KEY,DAT:MD_KEY,TBL:PTR) ! POSITION FILE FREE(TABLE) ! EMPTY THE TABLE DO NEXT_PAGE ! DISPLAY A FULL PAGE FIRST_PAGE ROUTINE !DISPLAY FIRST PAGE FREE(TABLE) ! EMPTY THE TABLE CLEAR(DAT:RECORD,-1) ! CLEAR RECORD TO LOW VALUES CLEAR(TBL:PTR) ! ZERO RECORD POINTER SET(DAT:MD_KEY) ! POINT TO FIRST RECORD LOOP NDX = 1 TO COUNT ! FILL UP THE TABLE DO FILL_NEXT ! FILL A TABLE ENTRY IF NOT FOUND THEN BREAK. ! GET OUT IF NO RECORD . NDX = 1 ! SET TO TOP OF TABLE DO SHOW_PAGE ! DISPLAY THE PAGE LAST_PAGE ROUTINE !DISPLAY LAST PAGE NDX# = NDX ! SAVE SELECTOR POSITION FREE(TABLE) ! EMPTY THE TABLE CLEAR(DAT:RECORD,1) ! CLEAR RECORD TO HIGH VALUES CLEAR(TBL:PTR,1) ! CLEAR PTR TO HIGH VALUE SET(DAT:MD_KEY) ! POINT TO FIRST RECORD LOOP NDX = COUNT TO 1 BY -1 ! FILL UP THE TABLE DO FILL_PREV ! FILL A TABLE ENTRY IF NOT FOUND THEN BREAK. ! GET OUT IF NO RECORD . NDX = NDX# ! RESTORE SELECTOR POSITION DO SHOW_PAGE ! DISPLAY THE PAGE FIND_RECORD ROUTINE !POSITION TO SPECIFIC RECORD SET(DAT:MD_KEY,DAT:MD_KEY,NEWPTR) !POSITION FILE IF NEWPTR = 0 !NEWPTR NOT SET NEXT(DATES) ! READ NEXT RECORD NEWPTR = POINTER(DATES) ! SET NEWPTR SKIP(DATES,-1) ! BACK UP TO DISPLAY RECORD . FREE(TABLE) ! CLEAR THE RECORD DO NEXT_PAGE ! DISPLAY A PAGE NEXT_PAGE ROUTINE !DISPLAY NEXT PAGE SAVECNT# = RECORDS(TABLE) ! SAVE RECORD COUNT LOOP COUNT TIMES ! FILL UP THE TABLE DO FILL_NEXT ! FILL A TABLE ENTRY IF NOT FOUND ! IF NONE ARE LEFT IF NOT SAVECNT# ! IF REBUILDING TABLE DO LAST_PAGE ! FILL IN RECORDS EXIT ! EXIT OUT OF ROUTINE . BREAK ! EXIT LOOP . . DO SHOW_PAGE ! DISPLAY THE PAGE SET_NEXT ROUTINE !POINT TO THE NEXT PAGE GET(TABLE,RECORDS(TABLE)) ! GET THE LAST TABLE ENTRY DO FILL_RECORD ! FILL IN THE RECORD SET(DAT:MD_KEY,DAT:MD_KEY,TBL:PTR) ! POSITION FILE NEXT(DATES) ! READ THE CURRENT RECORD FILL_NEXT ROUTINE !FILL NEXT TABLE ENTRY FOUND = FALSE ! ASSUME RECORD NOT FOUND LOOP UNTIL EOF(DATES) ! LOOP UNTIL END OF FILE NEXT(DATES) ! READ THE NEXT RECORD FOUND = TRUE ! SET RECORD FOUND DO FILL_TABLE ! FILL IN THE TABLE ENTRY ADD(TABLE) ! ADD LAST TABLE ENTRY GET(TABLE,RECORDS(TABLE)-COUNT) ! GET ANY OVERFLOW RECORD DELETE(TABLE) ! AND DELETE IT EXIT ! RETURN TO CALLER . PREV_PAGE ROUTINE !DISPLAY PREVIOUS PAGE LOOP COUNT TIMES ! FILL UP THE TABLE DO FILL_PREV ! FILL A TABLE ENTRY IF NOT FOUND THEN BREAK. ! GET OUT IF NO RECORD . DO SHOW_PAGE ! DISPLAY THE PAGE SET_PREV ROUTINE !POINT TO PREVIOUS PAGE GET(TABLE,1) ! GET THE FIRST TABLE ENTRY DO FILL_RECORD ! FILL IN THE RECORD SET(DAT:MD_KEY,DAT:MD_KEY,TBL:PTR) ! POSITION FILE PREVIOUS(DATES) ! READ THE CURRENT RECORD FILL_PREV ROUTINE !FILL PREVIOUS TABLE ENTRY FOUND = FALSE ! ASSUME RECORD NOT FOUND LOOP UNTIL BOF(DATES) ! LOOP UNTIL BEGINNING OF FILE PREVIOUS(DATES) ! READ THE PREVIOUS RECORD FOUND = TRUE ! SET RECORD FOUND DO FILL_TABLE ! FILL IN THE TABLE ENTRY ADD(TABLE,1) ! ADD FIRST TABLE ENTRY GET(TABLE,COUNT+1) ! GET ANY OVERFLOW RECORD DELETE(TABLE) ! AND DELETE IT EXIT ! RETURN TO CALLER . SHOW_PAGE ROUTINE !DISPLAY THE PAGE NDX# = NDX ! SAVE SCREEN INDEX LOOP NDX = 1 TO RECORDS(TABLE) ! LOOP THRU THE TABLE GET(TABLE,NDX) ! GET A TABLE ENTRY DO FILL_SCREEN ! AND DISPLAY IT IF TBL:PTR = NEWPTR ! SET INDEX FOR NEW RECORD NDX# = NDX ! POINT TO CORRECT RECORD . . LOOP WHILE NDX <= COUNT ! FINISH BLANKING THE SCREEN BLANK(ROW(?POINT),COL(?POINT),ROWS(?POINT),COLS(?POINT))!BLANK A LINE NDX += 1 ! INCREMENT NDX . NDX = NDX# ! RESTORE SCREEN INDEX NEWPTR = 0 ! CLEAR NEW RECORD POINTER CLEAR(DAT:RECORD) ! CLEAR RECORD AREA FILL_TABLE ROUTINE !MOVE FILE TO TABLE TBL:EVENT = DAT:EVENT TBL:MNTHDAY = DAT:MNTHDAY TBL:PTR = POINTER(DATES) ! SAVE RECORD POINTER TBL:DATE = dat:mnthday TBL:L2 = '³' IF dat:ltime > 1 !EVALUATE CONDITION TBL:TIME = format(dat:ltime,@t3) ! CONDITION IS TRUE ELSE !OTHERWISE TBL:TIME = '' ! CONDITION IS FALSE . TBL:L3 = '³' FILL_RECORD ROUTINE !MOVE TABLE TO FILE DAT:MNTHDAY = TBL:MNTHDAY FILL_SCREEN ROUTINE !MOVE TABLE TO SCREEN SCR:DATE = TBL:DATE SCR:L2 = TBL:L2 SCR:TIME = TBL:TIME SCR:L3 = TBL:L3 SCR:EVENT = TBL:EVENT GET_RECORD ROUTINE !GET SELECTED RECORD GET(TABLE,NDX) ! GET TABLE ENTRY GET(DATES,TBL:PTR) ! GET THE RECORD !! ---- End of Entdates ----- !!