home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / basic / library / qb_pds / database / tdb / tdb.bas < prev    next >
Encoding:
BASIC Source File  |  1992-01-22  |  22.4 KB  |  868 lines

  1. DECLARE FUNCTION CompareRecords% (index1%, index2%)
  2. DECLARE SUB ShowMessage (message$)
  3. DECLARE SUB ClearMessage ()
  4. DECLARE FUNCTION GetYesNo% (prompt$)
  5. DECLARE SUB LoadRecords ()
  6. DECLARE SUB SaveRecords ()
  7. DECLARE SUB ClearFields ()
  8. DECLARE SUB KbdEdit (buffer$, maxlen%, fg%, bg%, cancel%)
  9. DECLARE SUB AddRecord ()
  10. DECLARE SUB DeleteRecord ()
  11. DECLARE SUB EditRecord ()
  12. DECLARE SUB SortRecords ()
  13. DECLARE SUB FindRecord ()
  14. DECLARE SUB PrevRecord ()
  15. DECLARE SUB NextRecord ()
  16. DECLARE SUB PrintRecords ()
  17. DECLARE SUB ErrBeep ()
  18. DECLARE FUNCTION GetKey$ ()
  19. DECLARE SUB Help ()
  20. DECLARE SUB ShowRecord ()
  21. DECLARE SUB Terminate (confirm%)
  22. DECLARE SUB PaintDisplay ()
  23. DECLARE SUB Frame (top%, bottom%, left%, right%)
  24.  
  25. DEFINT A-Z
  26. '
  27. ' The Telephone Data Base, Version 1.00, Copyright (c) 1992 SoftCircuits
  28. ' Redistributed by permission
  29. '
  30. '  SoftCircuits Programming
  31. '  P.O. Box 16262
  32. '  Irvine, CA 92713
  33. '
  34. ' This program may be used and distributed freely on the condition
  35. ' that no fee is charged for such use and distribution with the
  36. ' exception of reasonable media and shipping charges.
  37. '
  38. ' This program may not be used for commercial purposes without
  39. ' written permission from SoftCircuits Programming.
  40. '
  41.  
  42. CONST MAXLAST = 25
  43. CONST MAXFIRST = 25
  44. CONST MAXPHONE = 20
  45. CONST MAXSTREET = 20
  46. CONST MAXCITY = 20
  47. CONST MAXSTATE = 2
  48. CONST MAXZIP = 10
  49.  
  50. CONST FIRSTROW = 7, FIRSTCOL = 27
  51. CONST LASTROW = 9, LASTCOL = 26
  52. CONST PHONEROW = 11, PHONECOL = 29
  53. CONST STREETROW = 13, STREETCOL = 23
  54. CONST CITYROW = 15, CITYCOL = 21
  55. CONST STATEROW = 17, STATECOL = 22
  56. CONST ZIPROW = 17, ZIPCOL = (STATECOL + MAXSTATE) + 16
  57.  
  58. CONST WINTOP = 5, WINBOTTOM = 19
  59. CONST WINLEFT = 10, WINRIGHT = 70
  60.  
  61. CONST MESSAGEROW = 22
  62.  
  63. 'Makes arrays dynamic
  64. '$DYNAMIC
  65.  
  66. TYPE record
  67.    first AS STRING * MAXFIRST
  68.    last AS STRING * MAXLAST
  69.    phone AS STRING * MAXPHONE
  70.    street AS STRING * MAXSTREET
  71.    city AS STRING * MAXCITY
  72.    state AS STRING * MAXSTATE
  73.    zip AS STRING * MAXZIP
  74. END TYPE
  75.  
  76. COMMON SHARED scrnFg
  77. COMMON SHARED scrnBg
  78. COMMON SHARED winFg
  79. COMMON SHARED winBg
  80. COMMON SHARED statFg
  81. COMMON SHARED statBg
  82.  
  83. COMMON SHARED numRecords
  84. COMMON SHARED currRecord
  85.  
  86.    DIM SHARED records(0) AS record
  87.    numRecords = 0
  88.    currRecord = 0
  89.   
  90.    scrnFg = 7              'Default black and white colors
  91.    scrnBg = 0
  92.    winFg = 0
  93.    winBg = 7
  94.    statFg = 0
  95.    statBg = 7
  96.  
  97.    'If display adapter is emulating CGA and /b switch not given
  98.    'then set colors to work on color display
  99.    IF INSTR(UCASE$(COMMAND$), "/B") = 0 THEN
  100.       DEF SEG = &H40
  101.       IF (PEEK(&H10) AND &H30) <> &H30 THEN
  102.          scrnFg = 11
  103.          scrnBg = 1
  104.          winFg = 0
  105.          winBg = 7
  106.          statFg = 0
  107.          statBg = 3
  108.       END IF
  109.    END IF
  110.  
  111.    CALL LoadRecords
  112.    CALL PaintDisplay
  113.  
  114.    DO
  115.       SELECT CASE GetKey$
  116.          CASE CHR$(&H0) + CHR$(&H3B)   'F1 (Help)
  117.             CALL Help
  118.          CASE CHR$(&H0) + CHR$(&H3C)   'F2 (Add)
  119.             CALL AddRecord
  120.          CASE CHR$(&H0) + CHR$(&H3D)   'F3 (Delete)
  121.             CALL DeleteRecord
  122.          CASE CHR$(&H0) + CHR$(&H3E)   'F4 (Edit)
  123.             CALL EditRecord
  124.          CASE CHR$(&H0) + CHR$(&H3F)   'F5 (Sort)
  125.             CALL SortRecords
  126.          CASE CHR$(&H0) + CHR$(&H40)   'F6 (Find)
  127.             CALL FindRecord
  128.          CASE CHR$(&H0) + CHR$(&H41)   'F7 (Previous)
  129.             CALL PrevRecord
  130.          CASE CHR$(&H0) + CHR$(&H42)   'F8 (Next)
  131.             CALL NextRecord
  132.          CASE CHR$(&H0) + CHR$(&H5A)   'Shift+F7 (First)
  133.             IF currRecord > 1 THEN currRecord = 1
  134.             CALL ShowRecord
  135.          CASE CHR$(&H0) + CHR$(&H5B)   'Shift+F8 (Last)
  136.             IF currRecord < numRecords THEN currRecord = numRecords
  137.             CALL ShowRecord
  138.          CASE CHR$(&H0) + CHR$(&H43)   'F9 (Print)
  139.             CALL PrintRecords
  140.          CASE CHR$(&H0) + CHR$(&H44)   'F10 (Quit)
  141.             CALL Terminate(confirm)
  142.             IF confirm THEN EXIT DO
  143.          CASE ELSE
  144.             CALL ErrBeep
  145.       END SELECT
  146.    LOOP
  147.  
  148.    COLOR 7, 0, 0
  149.    CLS
  150.  
  151. END
  152.  
  153. REM $STATIC
  154. '
  155. ' Adds a new record to the database and makes it the current record
  156. '
  157. SUB AddRecord
  158.  
  159.    DIM newEntry AS record        'Temporary record
  160.  
  161.    COLOR winFg, winBg
  162.    CALL ClearFields              'Clear current record from window
  163.  
  164.    LOCATE FIRSTROW, FIRSTCOL     'Let user type in information
  165.    CALL KbdEdit(newEntry.first, MAXFIRST, winFg, winBg, cancel)
  166.    IF cancel THEN GOTO cancelEntry
  167.    LOCATE LASTROW, LASTCOL
  168.    CALL KbdEdit(newEntry.last, MAXLAST, winFg, winBg, cancel)
  169.    IF cancel THEN GOTO cancelEntry
  170.    LOCATE PHONEROW, PHONECOL
  171.    CALL KbdEdit(newEntry.phone, MAXPHONE, winFg, winBg, cancel)
  172.    IF cancel THEN GOTO cancelEntry
  173.    LOCATE STREETROW, STREETCOL
  174.    CALL KbdEdit(newEntry.street, MAXSTREET, winFg, winBg, cancel)
  175.    IF cancel THEN GOTO cancelEntry
  176.    LOCATE CITYROW, CITYCOL
  177.    CALL KbdEdit(newEntry.city, MAXCITY, winFg, winBg, cancel)
  178.    IF cancel THEN GOTO cancelEntry
  179.    LOCATE STATEROW, STATECOL
  180.    CALL KbdEdit(newEntry.state, MAXSTATE, winFg, winBg, cancel)
  181.    IF cancel THEN GOTO cancelEntry
  182.    LOCATE ZIPROW, ZIPCOL
  183.    CALL KbdEdit(newEntry.zip, MAXZIP, winFg, winBg, cancel)
  184.    IF cancel THEN GOTO cancelEntry
  185.  
  186.    'Allocate temporary storage for records
  187.    REDIM temp(numRecords) AS record
  188.    FOR i = 1 TO numRecords
  189.       temp(i) = records(i)
  190.    NEXT i
  191.  
  192.    'Resize records array and restore records
  193.    REDIM records(numRecords + 1) AS record
  194.    FOR i = 1 TO numRecords
  195.       records(i) = temp(i)
  196.    NEXT i
  197.    ERASE temp
  198.  
  199.    numRecords = numRecords + 1
  200.    currRecord = numRecords
  201.    records(currRecord) = newEntry
  202.  
  203. cancelEntry:
  204.    CALL ShowRecord               'Update display
  205.  
  206. END SUB
  207.  
  208. '
  209. ' Clears all record fields using the current color
  210. '
  211. SUB ClearFields
  212.  
  213.    LOCATE FIRSTROW, FIRSTCOL:    PRINT SPACE$(MAXFIRST)
  214.    LOCATE LASTROW, LASTCOL:      PRINT SPACE$(MAXLAST)
  215.    LOCATE PHONEROW, PHONECOL:    PRINT SPACE$(MAXPHONE)
  216.    LOCATE STREETROW, STREETCOL:  PRINT SPACE$(MAXSTREET)
  217.    LOCATE CITYROW, CITYCOL:      PRINT SPACE$(MAXCITY)
  218.    LOCATE STATEROW, STATECOL:    PRINT SPACE$(MAXSTATE)
  219.    LOCATE ZIPROW, ZIPCOL:        PRINT SPACE$(MAXZIP)
  220.  
  221. END SUB
  222.  
  223. '
  224. ' Clears the current message from the message area
  225. '
  226. SUB ClearMessage
  227.  
  228.    COLOR scrnFg, scrnBg
  229.    LOCATE MESSAGEROW, 1
  230.    PRINT SPACE$(80)
  231.  
  232. END SUB
  233.  
  234. '
  235. ' Compares two records. Returns 1 if the first record should
  236. ' come after the second. Otherwise 0 is returned.
  237. '
  238. FUNCTION CompareRecords (index1, index2)
  239.  
  240.    CompareRecords = 0
  241.  
  242.    IF UCASE$(records(index1).last) > UCASE$(records(index2).last) THEN
  243.       CompareRecords = 1
  244.    ELSEIF UCASE$(records(index1).last) = UCASE$(records(index2).last) THEN
  245.       IF UCASE$(records(index1).first) > UCASE$(records(index2).last) THEN
  246.          CompareRecords = 1
  247.       END IF
  248.    END IF
  249.  
  250. END FUNCTION
  251.  
  252. '
  253. ' Deletes the current record (after confirmation)
  254. '
  255. SUB DeleteRecord
  256.  
  257.    IF numRecords > 0 THEN     'Must be something to delete
  258.  
  259.       IF GetYesNo("Delete the current record [Y/N]?") THEN
  260.  
  261.          'Allocate temporary storage for records
  262.          REDIM temp(numRecords - 1) AS record
  263.         
  264.          'Fill temporary array with all records except
  265.          'the current record
  266.          FOR i = 1 TO (currRecord - 1)
  267.             temp(i) = records(i)
  268.          NEXT i
  269.          FOR i = currRecord TO (numRecords - 1)
  270.             temp(i) = records(i + 1)
  271.          NEXT i
  272.  
  273.          'One less record
  274.          numRecords = numRecords - 1
  275.  
  276.          'Resize records array and restore records
  277.          REDIM records(numRecords) AS record
  278.          FOR i = 1 TO numRecords
  279.             records(i) = temp(i)
  280.          NEXT i
  281.          ERASE temp
  282.  
  283.          'Make sure currRecord remains within range
  284.          IF currRecord > numRecords THEN currRecord = numRecords
  285.         
  286.          CALL ShowRecord      'Update display
  287.  
  288.       END IF
  289.  
  290.    END IF
  291.  
  292. END SUB
  293.  
  294. '
  295. ' Allows the user to edit the current record
  296. '
  297. SUB EditRecord
  298.  
  299.    DIM newEntry AS record        'Temporary record
  300.  
  301.    IF currRecord = 0 THEN        'Nothing to edit
  302.       CALL ErrBeep
  303.       EXIT SUB
  304.    END IF
  305.  
  306.    CALL ShowMessage("Edit the current field  <Enter>=Next field  <Esc>=Cancel")
  307.    newEntry = records(currRecord)
  308.  
  309.    COLOR statFg, statBg          'Edit record a field at a time
  310.    LOCATE FIRSTROW, FIRSTCOL
  311.    CALL KbdEdit(newEntry.first, MAXFIRST, winFg, winBg, cancel)
  312.    IF cancel THEN GOTO cancelEdit
  313.    LOCATE LASTROW, LASTCOL
  314.    CALL KbdEdit(newEntry.last, MAXLAST, winFg, winBg, cancel)
  315.    IF cancel THEN GOTO cancelEdit
  316.    LOCATE PHONEROW, PHONECOL
  317.    CALL KbdEdit(newEntry.phone, MAXPHONE, winFg, winBg, cancel)
  318.    IF cancel THEN GOTO cancelEdit
  319.    LOCATE STREETROW, STREETCOL
  320.    CALL KbdEdit(newEntry.street, MAXSTREET, winFg, winBg, cancel)
  321.    IF cancel THEN GOTO cancelEdit
  322.    LOCATE CITYROW, CITYCOL
  323.    CALL KbdEdit(newEntry.city, MAXCITY, winFg, winBg, cancel)
  324.    IF cancel THEN GOTO cancelEdit
  325.    LOCATE STATEROW, STATECOL
  326.    CALL KbdEdit(newEntry.state, MAXSTATE, winFg, winBg, cancel)
  327.    IF cancel THEN GOTO cancelEdit
  328.    LOCATE ZIPROW, ZIPCOL
  329.    CALL KbdEdit(newEntry.zip, MAXZIP, winFg, winBg, cancel)
  330.    IF cancel THEN GOTO cancelEdit
  331.  
  332.    records(currRecord) = newEntry
  333.  
  334. cancelEdit:
  335.    CALL ShowRecord               'Update display
  336.    CALL ClearMessage
  337.  
  338. END SUB
  339.  
  340. '
  341. ' Sounds the computers internal speaker
  342. '
  343. SUB ErrBeep
  344.  
  345.    SOUND 800, 2
  346.    SOUND 400, 2
  347.   
  348.    WHILE INKEY$ <> "": WEND         'Flush keyboard buffer
  349.  
  350. END SUB
  351.  
  352. '
  353. ' Searches the database for a given string (not case sensitive)
  354. '
  355. SUB FindRecord
  356.  
  357.    'Get input and convert to upper case
  358.    LOCATE MESSAGEROW, 15
  359.    COLOR scrnFg, scrnBg
  360.    PRINT "Enter search string: ";
  361.    CALL KbdEdit(inputString$, 30, scrnFg, scrnBg, cancel)
  362.    CALL ClearMessage
  363.  
  364.    IF cancel = 1 THEN EXIT SUB
  365.    searchString$ = UCASE$(inputString$)
  366.  
  367.    'Scan records for match
  368.    FOR i = 1 TO numRecords
  369.       found = 0
  370.       IF INSTR(UCASE$(records(i).first), searchString$) <> 0 THEN
  371.          found = 1
  372.       ELSEIF INSTR(UCASE$(records(i).last), searchString$) <> 0 THEN
  373.          found = 1
  374.       ELSEIF INSTR(UCASE$(records(i).phone), searchString$) <> 0 THEN
  375.          found = 1
  376.       ELSEIF INSTR(UCASE$(records(i).street), searchString$) <> 0 THEN
  377.          found = 1
  378.       ELSEIF INSTR(UCASE$(records(i).city), searchString$) <> 0 THEN
  379.          found = 1
  380.       ELSEIF INSTR(UCASE$(records(i).state), searchString$) <> 0 THEN
  381.          found = 1
  382.       ELSEIF INSTR(UCASE$(records(i).zip), searchString$) <> 0 THEN
  383.          found = 1
  384.       END IF
  385.  
  386.       'If a match was found, show matching record and
  387.       'ask if the search should continue
  388.       IF found = 1 THEN
  389.          currRecord = i
  390.          CALL ShowRecord
  391.          IF GetYesNo("Find next match [Y/N]?") = 0 THEN EXIT SUB
  392.       END IF
  393.    NEXT i
  394.  
  395.    'Tell user no more matches found
  396.    a$ = "Match not found for " + CHR$(&H22) + inputString$
  397.    a$ = a$ + CHR$(&H22) + ", press any key"
  398.    CALL ShowMessage(a$)
  399.    a$ = GetKey$
  400.    CALL ClearMessage
  401.  
  402. END SUB
  403.  
  404. '
  405. ' Displays a box with the specified coordinates
  406. ' The inside of the box is cleared to the current color
  407. '
  408. SUB Frame (top, bottom, left, right)
  409.  
  410.    LOCATE top, left
  411.    PRINT CHR$(&HC9); STRING$((right - left) - 1, CHR$(&HCD)); CHR$(&HBB);
  412.   
  413.    FOR row = (top + 1) TO (bottom - 1)
  414.       LOCATE row, left
  415.       PRINT CHR$(&HBA); SPACE$((right - left) - 1); CHR$(&HBA);
  416.    NEXT row
  417.  
  418.    LOCATE bottom, left
  419.    PRINT CHR$(&HC8); STRING$((right - left) - 1, CHR$(&HCD)); CHR$(&HBC);
  420.  
  421. END SUB
  422.  
  423. '
  424. ' Returns the next available keystroke (read with INKEY$)
  425. '
  426. FUNCTION GetKey$
  427.  
  428.    ch$ = "": WHILE ch$ = "": ch$ = INKEY$: WEND
  429.    GetKey$ = ch$
  430.  
  431. END FUNCTION
  432.  
  433. '
  434. ' Displays the given prompt and gets a yes/no response from the user
  435. ' Returns 1 if "Y" was pressed or 0 if "N" was pressed
  436. '
  437. FUNCTION GetYesNo (prompt$)
  438.  
  439.    CALL ShowMessage(prompt$)
  440.  
  441.    DO
  442.       a$ = UCASE$(GetKey$)             'Wait for "Y" or "N"
  443.       IF a$ = "Y" OR a$ = "N" THEN
  444.          EXIT DO
  445.       ELSE
  446.          CALL ErrBeep
  447.       END IF
  448.    LOOP
  449.  
  450.    CALL ClearMessage
  451.  
  452.    IF a$ = "Y" THEN GetYesNo = 1 ELSE GetYesNo = 0
  453.  
  454. END FUNCTION
  455.  
  456. '
  457. ' Displays help screen
  458. '
  459. SUB Help
  460.  
  461.    COLOR winFg, winBg
  462.    CALL Frame(5, 19, 3, 78)   'Create help window
  463.  
  464.    LOCATE 7, 33               'Display help info
  465.    PRINT "Help Screen"
  466.  
  467.    tab1 = 7
  468.    tab2 = 44
  469.    LOCATE 9, tab1
  470.    PRINT "<F1>=Help (this screen)";
  471.    LOCATE , tab2
  472.    PRINT "<F2>=Add a new record"
  473.    LOCATE , tab1
  474.    PRINT "<F3>=Delete the current record";
  475.    LOCATE , tab2
  476.    PRINT "<F4>=Edit the current record"
  477.    LOCATE , tab1
  478.    PRINT "<F5>=Sort records";
  479.    LOCATE , tab2
  480.    PRINT "<F6>=Find a record"
  481.    LOCATE , tab1
  482.    PRINT "<F7>=Show the previous record";
  483.    LOCATE , tab2
  484.    PRINT "<F8>=Show the next record"
  485.    LOCATE , tab1
  486.    PRINT "<Shift+F7>=Show the first record";
  487.    LOCATE , tab2
  488.    PRINT "<Shift+F8>=Show the last record"
  489.    LOCATE , tab1
  490.    PRINT "<F9>=Send records to a printer";
  491.    LOCATE , tab2
  492.    PRINT "<F10>=Save records and quit"
  493.  
  494.    LOCATE 17, 27
  495.    PRINT "Press any key to exit help"
  496.    a$ = GetKey$
  497.  
  498.    CALL PaintDisplay          'Restore screen
  499.  
  500. END SUB
  501.  
  502. '
  503. '  Keyboard editor, recognizes Escape,
  504. '  If first key pressed is an edit key the old string is edited
  505. '  otherwise, the old string is discarded
  506. '
  507. SUB KbdEdit (buffer$, maxlen, fg, bg, cancel)
  508.  
  509.    row = CSRLIN               'Save cursor position
  510.    col = POS(0)
  511.  
  512.    'Remove trailing spaces or uninitialized 0's
  513.    IF LEFT$(buffer$, 1) = CHR$(0) THEN buffer$ = ""
  514.    buffer$ = RTRIM$(buffer$)
  515.   
  516.    LOCATE row, col, 1         'Display string in inverse video
  517.    COLOR fg, bg
  518.    PRINT STRING$(maxlen, CHR$(&HF9));
  519.    LOCATE row, col
  520.    COLOR bg, fg
  521.    PRINT buffer$;
  522.    COLOR fg, bg
  523.   
  524.    a$ = GetKey$               'Get a key
  525.  
  526.    'If the key was a edit key, we will edit the original string
  527.    'otherwise, we assume the user's typing a new string and the
  528.    'original is discarded
  529.    IF a$ >= " " AND a$ <= "~" THEN
  530.       temp$ = ""
  531.    ELSE
  532.       temp$ = buffer$
  533.    END IF
  534.    posn = LEN(temp$)
  535.  
  536.    done = 0                   '0 until <Esc> or <Enter> is pressed
  537.    first = 1                  'Indicates first time through
  538.  
  539.    DO
  540.       'Don't read a new key if it's our first time through
  541.       IF first = 1 THEN
  542.          first = 0
  543.       ELSE
  544.          LOCATE row, col
  545.          PRINT temp$; STRING$(maxlen - LEN(temp$), CHR$(&HF9))
  546.          LOCATE row, col + posn
  547.          a$ = GetKey$
  548.       END IF
  549.  
  550.       SELECT CASE a$
  551.          CASE " " TO "~"
  552.             IF LEN(temp$) < maxlen THEN
  553.                first$ = LEFT$(temp$, posn)
  554.                last$ = RIGHT$(temp$, LEN(temp$) - posn)
  555.                temp$ = first$ + a$ + last$
  556.                posn = posn + 1
  557.             ELSE
  558.                CALL ErrBeep
  559.             END IF
  560.          CASE CHR$(8)               'Backspace
  561.             IF posn > 0 THEN
  562.                first$ = LEFT$(temp$, posn - 1)
  563.                last$ = RIGHT$(temp$, LEN(temp$) - posn)
  564.                temp$ = first$ + last$
  565.                posn = posn - 1
  566.             ELSE
  567.                CALL ErrBeep
  568.             END IF
  569.          CASE CHR$(0) + CHR$(&H53)  'Delete
  570.             IF posn < LEN(temp$) THEN
  571.                first$ = LEFT$(temp$, posn)
  572.                last$ = RIGHT$(temp$, LEN(temp$) - (posn + 1))
  573.                temp$ = first$ + last$
  574.             ELSE
  575.                CALL ErrBeep
  576.             END IF
  577.          CASE CHR$(0) + CHR$(&H4B)  'Left
  578.             IF posn > 0 THEN
  579.                posn = posn - 1
  580.             ELSE
  581.                CALL ErrBeep
  582.             END IF
  583.          CASE CHR$(0) + CHR$(&H4D)  'Right
  584.             IF posn < LEN(temp$) THEN
  585.                posn = posn + 1
  586.             ELSE
  587.                CALL ErrBeep
  588.             END IF
  589.          CASE CHR$(0) + CHR$(&H47)  'Home
  590.             posn = 0
  591.          CASE CHR$(0) + CHR$(&H4F)  'End
  592.             posn = LEN(temp$)
  593.          CASE CHR$(13)              'Enter (Accept)
  594.             buffer$ = temp$
  595.             done = 1
  596.             cancel = 0
  597.          CASE CHR$(27)              'Escape (Cancel)
  598.             done = 1
  599.             cancel = 1
  600.          CASE ELSE
  601.             CALL ErrBeep
  602.       END SELECT
  603.  
  604.    LOOP UNTIL done
  605.   
  606.    COLOR fg, bg                     'Display the resulting string
  607.    LOCATE row, col, 0
  608.    PRINT buffer$; SPACE$(maxlen - LEN(buffer$))
  609.  
  610. END SUB
  611.  
  612. '
  613. ' Loads a database from disk
  614. '
  615. SUB LoadRecords
  616.  
  617.    CALL ShowMessage("Loading records...")
  618.  
  619.    'Open data file
  620.    OPEN "TDB.DAT" FOR RANDOM AS #1 LEN = LEN(records(0))
  621.  
  622.    'Calculate numRecords and allocate records array
  623.    numRecords = LOF(1) \ LEN(records(0))
  624.    REDIM records(numRecords) AS record
  625.  
  626.    'Read records
  627.    FOR i = 1 TO numRecords
  628.       GET #1, i, records(i)
  629.    NEXT i
  630.    CLOSE #1
  631.  
  632.    IF numRecords > 0 THEN currRecord = 1
  633.  
  634.    CALL ClearMessage
  635.  
  636. END SUB
  637.  
  638. '
  639. ' Makes the next record the current record
  640. '
  641. SUB NextRecord
  642.  
  643.    IF currRecord < numRecords THEN
  644.       currRecord = currRecord + 1
  645.       CALL ShowRecord
  646.    ELSE
  647.       CALL ErrBeep
  648.    END IF
  649.  
  650. END SUB
  651.  
  652. '
  653. ' Creates the main display and calls ShowRecord
  654. '
  655. SUB PaintDisplay
  656.  
  657.    COLOR scrnFg, scrnBg, scrnBg        'Clear screen
  658.    CLS
  659.  
  660.    COLOR statFg, statBg                'Create title status bar
  661.    LOCATE 1, 1: PRINT SPACE$(80)
  662.    LOCATE 1, 20: PRINT "The Telephone Data Base, Version 1.00"
  663.  
  664.    COLOR winFg, winBg                  'Create record window
  665.    CALL Frame(WINTOP, WINBOTTOM, WINLEFT, WINRIGHT)
  666.  
  667.    LOCATE LASTROW, LASTCOL - 11        'Print field labels
  668.    PRINT "Last Name:"
  669.    LOCATE FIRSTROW, FIRSTCOL - 12
  670.    PRINT "First Name:"
  671.    LOCATE PHONEROW, PHONECOL - 14
  672.    PRINT "Phone Number:"
  673.    LOCATE STREETROW, STREETCOL - 8
  674.    PRINT "Street:"
  675.    LOCATE CITYROW, CITYCOL - 6
  676.    PRINT "City:"
  677.    LOCATE STATEROW, STATECOL - 7
  678.    PRINT "State:"
  679.    LOCATE ZIPROW, ZIPCOL - 10
  680.    PRINT "Zip Code:"
  681.  
  682.    LOCATE 25, 1                        'Display function-key bar
  683.    COLOR scrnFg, scrnBg: PRINT "1";
  684.    COLOR statFg, statBg: PRINT "Help  ";
  685.    COLOR scrnFg, scrnBg: PRINT " 2";
  686.    COLOR statFg, statBg: PRINT "Add   ";
  687.    COLOR scrnFg, scrnBg: PRINT " 3";
  688.    COLOR statFg, statBg: PRINT "Delete";
  689.    COLOR scrnFg, scrnBg: PRINT " 4";
  690.    COLOR statFg, statBg: PRINT "Edit  ";
  691.    COLOR scrnFg, scrnBg: PRINT " 5";
  692.    COLOR statFg, statBg: PRINT "Sort  ";
  693.    COLOR scrnFg, scrnBg: PRINT " 6";
  694.    COLOR statFg, statBg: PRINT "Find  ";
  695.    COLOR scrnFg, scrnBg: PRINT " 7";
  696.    COLOR statFg, statBg: PRINT "Prev  ";
  697.    COLOR scrnFg, scrnBg: PRINT " 8";
  698.    COLOR statFg, statBg: PRINT "Next  ";
  699.    COLOR scrnFg, scrnBg: PRINT " 9";
  700.    COLOR statFg, statBg: PRINT "Print ";
  701.    COLOR scrnFg, scrnBg: PRINT " 10";
  702.    COLOR statFg, statBg: PRINT "Quit  ";
  703.  
  704.    CALL ShowRecord                     'Display current record
  705.  
  706. END SUB
  707.  
  708. '
  709. ' Makes the previous record the current record
  710. '
  711. SUB PrevRecord
  712.  
  713.    IF currRecord > 1 THEN
  714.       currRecord = currRecord - 1
  715.       CALL ShowRecord
  716.    ELSE
  717.       CALL ErrBeep
  718.    END IF
  719.  
  720. END SUB
  721.  
  722. '
  723. ' Send the database to the printer
  724. '
  725. SUB PrintRecords
  726.  
  727.    IF GetYesNo("Send records to printer [Y/N]?") THEN
  728.       CALL ShowMessage("Printing records...")
  729.       FOR i = 1 TO numRecords
  730.          LPRINT RTRIM$(records(i).first); " ";
  731.          LPRINT RTRIM$(records(i).last); " ";
  732.          LPRINT RTRIM$(records(i).phone)
  733.          LPRINT RTRIM$(records(i).street)
  734.          LPRINT RTRIM$(records(i).city); " ";
  735.          LPRINT RTRIM$(records(i).state); " ";
  736.          LPRINT RTRIM$(records(i).zip)
  737.          LPRINT
  738.       NEXT i
  739.       CALL ClearMessage
  740.    END IF
  741.  
  742. END SUB
  743.  
  744. '
  745. ' Writes the database to disk
  746. '
  747. SUB SaveRecords
  748.  
  749.    IF GetYesNo("Save records to disk [Y/N]?") THEN
  750.       CALL ShowMessage("Saving records...")
  751.       KILL "TDB.DAT"
  752.  
  753.       'Open the data file
  754.       OPEN "TDB.DAT" FOR RANDOM AS #1 LEN = LEN(records(0))
  755.  
  756.       'Write the records to disk
  757.       FOR i = 1 TO numRecords
  758.          PUT #1, i, records(i)
  759.       NEXT i
  760.       CLOSE #1
  761.  
  762.       CALL ClearMessage
  763.    END IF
  764.  
  765. END SUB
  766.  
  767. '
  768. ' Displays the given message in the message area
  769. '
  770. SUB ShowMessage (message$)
  771.  
  772.    COLOR scrnFg, scrnBg
  773.    LOCATE MESSAGEROW, (80 - LEN(message$)) / 2    'Center message string
  774.    PRINT message$
  775.  
  776. END SUB
  777.  
  778. '
  779. ' Displays the current record
  780. '
  781. SUB ShowRecord
  782.  
  783.    COLOR winFg, winBg
  784.   
  785.    'Show current record number against number of records
  786.    LOCATE WINTOP, WINLEFT + 5
  787.    PRINT "["; currRecord; "/"; numRecords; "]"; STRING$(10, &HCD)
  788.  
  789.    IF numRecords = 0 THEN
  790.       CALL ClearFields
  791.    ELSE
  792.       LOCATE FIRSTROW, FIRSTCOL
  793.       PRINT records(currRecord).first
  794.       LOCATE LASTROW, LASTCOL
  795.       PRINT records(currRecord).last
  796.       LOCATE PHONEROW, PHONECOL
  797.       PRINT records(currRecord).phone
  798.       LOCATE STREETROW, STREETCOL
  799.       PRINT records(currRecord).street
  800.       LOCATE CITYROW, CITYCOL
  801.       PRINT records(currRecord).city
  802.       LOCATE STATEROW, STATECOL
  803.       PRINT records(currRecord).state
  804.       LOCATE ZIPROW, ZIPCOL
  805.       PRINT records(currRecord).zip
  806.    END IF
  807.  
  808. END SUB
  809.  
  810. '
  811. ' Uses a shell sort to sort all the records in the database.
  812. ' Records are compared by calling CompareRecords.
  813. '
  814. SUB SortRecords
  815.  
  816.    IF numRecords = 0 THEN        'Nothing to sort
  817.       CALL ErrBeep
  818.       EXIT SUB
  819.    END IF
  820.  
  821.    IF GetYesNo("Sort records [Y/N]?") THEN
  822.  
  823.       'Set comparison offset to half the number of records
  824.       offset = numRecords \ 2
  825.  
  826.       DO WHILE offset > 0        'Loop until offset gets to 0
  827.          limit = numRecords - offset
  828.          DO
  829.             switch = 0           'Assume no switches at this offset
  830.  
  831.             'Compare elements and switch those out of order
  832.             FOR i = 1 TO limit
  833.                IF CompareRecords(i, i + offset) THEN
  834.                   SWAP records(i), records(i + offset)
  835.                   switch = i
  836.                END IF
  837.             NEXT i
  838.  
  839.             'Sort on next pass only to where last switch was made
  840.             limit = switch - offset
  841.          LOOP WHILE switch
  842.  
  843.          'No switches at last offset, try one half as big
  844.          offset = offset \ 2
  845.  
  846.       LOOP
  847.       currRecord = 1             'Go to first record and update screen
  848.       CALL ShowRecord
  849.    END IF
  850.  
  851. END SUB
  852.  
  853. '
  854. ' Saves the records to disk and sets confirm to 1 if the user confirms
  855. ' they want to exit. Otherwise, confirm is set to 0
  856. '
  857. SUB Terminate (confirm)
  858.  
  859.    IF GetYesNo("Exit to DOS [Y/N]?") THEN
  860.       CALL SaveRecords
  861.       confirm = 1
  862.    ELSE
  863.       confirm = 0
  864.    END IF
  865.  
  866. END SUB
  867.  
  868.