home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / Basic / Samples / BOZOL2 / BOZOL2.ZIP / DATABASE.BAS < prev    next >
Encoding:
BASIC Source File  |  1994-02-08  |  22.0 KB  |  747 lines

  1. '=========================================================================
  2. '         dBASE III Plus file interface subroutines begin here
  3. '=========================================================================
  4. SUB dBSetIndexTo(IX$,Fld$,e%)
  5. e%=0
  6. ' Make sure a database is open
  7. IF dBASEOpen%=0 THEN e%=1:EXIT SUB
  8.  
  9. ' close existing index if it is open
  10. IF IX$="" OR Index$<>"" THEN Index$="":_
  11.    CALL BT("","Q","","","","",r%)
  12. IF IX$="" THEN EXIT SUB
  13. ' verify filename exists
  14. IF DIR$(IX$)="" THEN e%=3:EXIT SUB
  15.  
  16. ' verify field exists in database
  17. Fld%=0:Fld$=UCASE$(Fld$)
  18.     FOR y%=1 TO NumberOfFields?
  19.             IF INSTR(DBS(y%).FieldName,Fld$)=1 THEN Fld%=y%:EXIT FOR
  20.     NEXT y%
  21. IF Fld%=0 THEN e%=2:EXIT SUB
  22. Index$=IX$:IndexField$=Fld$:IndexField?=Fld%
  23. END SUB
  24.  
  25. SUB dBCreateIndex(IX$, Fld$, e%)
  26. REDIM K$(1000), D$(1000)
  27. Bt.Update.Always%=0
  28. ' Make sure a database is open
  29. IF dBASEOpen%=0 THEN e%=1:GOTO ExitSub
  30.  
  31. ' close existing index if it is open
  32. IF IX$="" OR Index$<>"" THEN Index$="":_
  33.    CALL BT("","Q","","","","",r%)
  34. IF IX$="" THEN EXIT SUB
  35.  
  36. ' verify field exists in database
  37. Fld%=0:Fld$=UCASE$(Fld$)
  38.     FOR y%=1 TO NumberOfFields?
  39.             IF INSTR(DBS(y%).FieldName,Fld$)=1 THEN Fld%=y%:EXIT FOR
  40.     NEXT y%
  41. IF Fld%=0 THEN e%=2:GOTO EXITSUB
  42. Index$=IX$:IndexField$=Fld$:IndexField?=Fld%
  43.  
  44. ' Create the index and build it.
  45. K$=SPACE$(DBS(Fld%).FieldLength):D$=CHR$(0,0,0,0)
  46. CALL BT(Index$,"C",K$,D$,RK$,RD$,R%)
  47. IF NOT R% THEN E%=3:GOTO EXITSUB ' could not create index
  48. x%=CSRLIN:y%=POS(0)
  49. For y???=1 TO NumberOfRecords???
  50.     dBGetRecord Y???, e%
  51.         IF e% THEN e%=4:EXIT FOR
  52.     IF INSTAT OR COMCHARS% THEN A$=BOZOINKEY$:IF A$=CHR$(27) THEN e%=5:EXIT FOR
  53.  
  54.         ' ====================
  55.         ' remove the UCASE$ here if you do not want the index to be
  56.         ' create as case insensative.
  57.         K$=UCASE$(dBGetCField$(Indexfield$, e%))
  58.         '  ^^^^^^____________________________ ^
  59.  
  60.         IF e% THEN e%=6:EXIT FOR
  61.         D$=MKDWD$(Y???)  ' must know the record number!
  62.         INCR i%
  63.         K$(i%)=K$:D$(i%)=D$
  64.         IF i%=1000 THEN
  65.             FOR ii%=1 TO 1000
  66.         CALL BT(Index$,"A",K$(ii%),D$(ii%),RK$,RD$,r%)
  67.             IF NOT r% THEN e%=7:EXIT FOR
  68.                 NEXT ii%
  69.                 i%=0
  70.                 IF e%=7 THEN EXIT FOR
  71.     END IF
  72.         X%=BOZOCSRLIN:Y%=BOZOPOS:BOZOPRINT STR$(Y???):BOZOLOCATE X%,Y%
  73.         NEXT y???
  74.  
  75.             FOR ii%=1 TO i%
  76.         CALL BT(Index$,"A",K$(ii%),D$(ii%),RK$,RD$,r%)
  77.             IF NOT r% THEN e%=7:EXIT FOR
  78.                 NEXT ii%
  79.  
  80.     CALL BT(Index$,"Q","","","","",r%)
  81. ExitSub:
  82. BT.Update.Always%=-1
  83. END SUB
  84.  
  85. SUB dBSearchIndex(Findme$,e%)
  86. e%=0
  87. IF dBaseOpen%=0 THEN e%=1:EXIT SUB
  88. IF Index$="" THEN
  89.         BOZOPRINT CrLf$+"Index not open, scan database? (Y/N): "
  90.         YN$=BOZOINPUT$
  91.     IF UCASE$(YN$)="Y" THEN
  92.         ' scan the whole database for a match
  93.         FOR y???=1 TO NumberOfRecords???
  94.                 dBGetRecord y???, e%
  95.                     IF e% THEN EXIT FOR
  96.                     IF INSTR(FindMe$,RecordBlock$) THEN EXIT FOR
  97.         NEXT y???
  98.         IF y???=>NumberOfRecords THEN _
  99.                 BOZOPRINT "Not Found.  Press a key..."
  100.                 CWAIT
  101.                 BOZOPRINT CrLf$
  102.         END IF
  103. ELSE
  104.         Findme$=UCASE$(Findme$)
  105.     CALL BT(Index$,"S", Findme$, D$, RK$, RD$, r%)
  106.         'IF NOT r% THEN e%=2:EXIT SUB
  107.         FindMe$=RK$
  108.         R???=CVDWD(RD$)
  109.         IF R???>0 THEN CALL dBGetRecord(R???,e%)
  110. END IF
  111. END SUB
  112.  
  113. SUB dBSkip(NS%, e%)
  114. e%=0
  115. IF LEN(INDEX$) THEN
  116.         DO
  117.     IF NS%<0 THEN BT Index$,"P","","",K$,D$,r%:INCR NS% ELSE _
  118.                       BT Index$,"N","","",K$,D$,r%:DECR NS%
  119.         IF NOT r% THEN e%=-1:EXIT SUB
  120.         IF INSTAT THEN IF A$=CHR$(27) THEN NS%=0
  121.         LOOP WHILE NS%<>0
  122.         dBGetRecord CVDWD(D$), e%
  123. ELSE
  124.     RN???=RecNum??? + NS%
  125.         IF RN??? < 1 THEN RN???=1:e%=-1
  126.         IF RN??? > NumberOfRecords??? THEN RN???=NumberOfRecords???:e%=-1
  127.         dBGetRecord RN???,e%
  128. END IF
  129. END SUB
  130.  
  131. SUB dBGotoTop (e%)
  132. e%=0
  133. IF LEN(INDEX$) THEN
  134.     BT Index$,"F","","",K$,D$,r%
  135.         IF NOT r% THEN e%=-2:EXIT SUB
  136.         DBGetRecord CVDWD(D$),e%
  137. ELSE
  138.     DBGetRecord 1, e%
  139. END IF
  140. END SUB
  141.  
  142. SUB dBGotoBottom (e%)
  143. e%=0
  144. IF LEN(INDEX$) THEN
  145.     BT Index$,"L","","",K$,D$,r%
  146.         IF NOT r% THEN e%=-2:EXIT SUB
  147.         DBGetRecord CVDWD(D$),e%
  148. ELSE
  149.     DBGetRecord NumberOfRecords???, e%
  150. END IF
  151. END SUB
  152.  
  153. SUB dBEditRecord (RN???, e%)
  154. e%=0
  155.     dBGetRecord RN???, e%
  156.         IF e% THEN EXIT SUB
  157.  
  158. ' remove entry from index
  159. IF LEN(INDEX$) THEN
  160.     BT Index$,"D",UCASE$(DBGetCField$(IndexField$,e%)),MKDWD$(RN???),"","",r%
  161.     IF NOT r% THEN BOZOPRINT "Error accessing index file"+CrLf$
  162. END IF
  163.  
  164.         ' edit the record
  165.         DBEditFields e%
  166.  
  167. ' replace entry in index
  168. IF LEN(INDEX$) THEN
  169.     BT Index$,"A", UCASE$(DBGetCField$(IndexField$,e%)),MKDWD$(RN???),"","",r%
  170.     IF NOT r% THEN BOZOPRINT "Error updating index file"+CrLf$
  171. END IF
  172. END SUB
  173.  
  174. SUB dBAppendRecord (e%)
  175.     e%=0
  176.         IF dBaseOpen%=0 THEN e%=1:EXIT SUB
  177.     Recnum???=0
  178.         RecordBlock$=SPACE$(LEN(RecordBlock$))
  179.     DbEditFields e%
  180.     IF Recnum???>0 AND LEN(INDEX$) THEN
  181.             BT Index$, "A", UCASE$(DBGetCField$(IndexField$,e%)),MKDWD$(RecNum???),"","",r%
  182.                 IF NOT r% THEN BOZOPRINT "Error appending index file."+CrLf$
  183.         END IF
  184. END SUB
  185.  
  186. SUB dBDefaultFormat
  187. ' Create a default field edit format.
  188. IF dBaseOpen%=0 THEN EXIT SUB
  189. REDIM DBE(256) AS DBaseEditFormat
  190. k%=1
  191. FOR y%=1 to NumberOfFields?
  192.         INCR j%:IF j%=20 THEN j%=1:k%=k%+40:IF K%=81 THEN EXIT FOR
  193.     DBE(y%).FieldName = DBS(y%).FieldName
  194.         DBE(y%).FieldType = DBS(y%).FieldType
  195.         DBE(y%).FieldLength = DBS(y%).FieldLength
  196.         DBE(y%).FieldRow = j%
  197.         DBE(y%).FieldCol = k%+(11-LEN(RTRIM$(DBS(y%).FieldName,CHR$(0))))
  198.     DBE(y%).FieldFG = 0
  199.         DBE(y%).FieldBG = 7
  200. NEXT y%
  201. END SUB
  202.  
  203. SUB dBCreateFormat
  204. IF dBaseOpen%=0 THEN BOZOPRINT "No Database is in USE."+CrLf$:EXIT SUB
  205. DO
  206. BOZOCLS
  207. DBView
  208. BOZOLOCATE 23,1:BOZOCOLOR 7,0:BOZOPRINT "Press ENTER to Accept or Fieldname to change: "
  209. F$=BOZOINPUT$
  210. IF F$="" THEN
  211.     B%=FREEFILE
  212.         BOZOLOCATE 23,1:BOZOPRINT SPACE$(80)
  213.         BOZOLOCATE 23,1:BOZOPRINT "Enter format filename: "
  214.         F$=BOZOINPUT$
  215.         IF F$="" THEN F$="NONAME.FMT"
  216.         OPEN F$ FOR RANDOM SHARED AS #B% LEN=LEN(DBE(1))
  217.         Fld%=1
  218.         DO UNTIL DBE(Fld%).FieldLength=0
  219.             PUT #B%, Fld%, DBE(Fld%)
  220.                 INCR Fld%
  221.         LOOP
  222.         EXIT LOOP
  223. ELSE
  224. Fld%=0
  225. F$=UCASE$(F$)
  226.     FOR y%=1 TO NumberOfFields?
  227.             IF INSTR(DBS(y%).FieldName,F$)=1 THEN Fld%=y%:EXIT FOR
  228.     NEXT y%
  229. IF Fld%=0 THEN BOZOLOCATE 23,1:BOZOPRINT SPACE$(80):BOZOLOCATE 23,1:BOZOPRINT "BAD FIELD NAME":SOUND 50,4:DELAY 2:ITERATE LOOP
  230. BOZOLOCATE 23,1:BOZOPRINT SPACE$(80):BOZOLOCATE 23,1:BOZOPRINT "Use arrow keys to place new field position"
  231. X%=DBE(Fld%).FieldRow
  232. Y%=DBE(Fld%).FieldCol
  233. F$=RTRIM$(DBE(Fld%).FieldName,CHR$(0))+":"+STRING$(DBE(Fld%).FieldLength,176)
  234. ' edit field location
  235. DBSCRNFIND X%, Y%, F$
  236. IF X%=0 THEN EXIT LOOP
  237. DBE(Fld%).FieldRow = X%
  238. DBE(Fld%).FieldCol = Y%
  239. END IF
  240. LOOP
  241. END SUB
  242.  
  243. SUB dBSetFormatTo(FormatFileName$,Ecode%)
  244. Ecode%=0
  245. IF FormatFileName$="" THEN ERASE DBE():EXIT SUB
  246. IF Dir$(FormatFileName$)="" THEN Ecode%=1:EXIT SUB
  247. B%=FREEFILE
  248. OPEN FormatFileName$ FOR RANDOM SHARED AS #B% LEN=LEN(DBE(1))
  249. FOR y%=1 TO LOF(B%)\LEN(DBE)
  250.     GET #B%, y%, DBE(y%)
  251. NEXT y%
  252. CLOSE #B%
  253. END SUB
  254.  
  255. SUB dBView
  256. Fld%=1
  257. of%=(PBVScrnTxtAttr AND &HF) ' get the original foreground and background
  258. ob%=(PBVScrnTxtAttr \ &H10)  ' BOZOCOLORs, in case they change.
  259. DO UNTIL DBE(Fld%).FieldLength=0
  260.     BOZOLOCATE DBE(Fld%).FieldRow,DBE(Fld%).FieldCol
  261.         BOZOCOLOR of%,ob%
  262.         BOZOPRINT RTRIM$(DBE(Fld%).FieldName,chr$(0))+":"
  263.         X%=BOZOCSRLIN:Y%=BOZOPOS
  264.         BOZOCOLOR DBE(Fld%).FieldFG,DBE(Fld%).FieldBG
  265.         BOZOPRINT SPACE$(DBE(Fld%).FieldLength)
  266.     BOZOLOCATE X%,Y%
  267.         IF DBE(Fld%).FieldType="N" THEN
  268.             BOZOPRINT LTRIM$(STR$(dBGetNField!((DBE(Fld%).FieldName),E%)))
  269.                 IF E% THEN BOZOPRINT "???"
  270.     ELSE
  271.             BOZOPRINT dBGetCField$((DBE(Fld%).FieldName),E%)
  272.                 IF E% THEN BOZOPRINT "???"
  273.     END IF
  274.     INCR Fld%
  275. LOOP
  276. BOZOCOLOR of%, ob%
  277. END SUB
  278.  
  279.  
  280. SUB dBEditFields(Ecode%)
  281. Ecode%=0
  282. Fld%=1 ' start with the first field on the screen
  283. of%=(PBVScrnTxtAttr AND &HF) ' get the original foreground and background
  284. ob%=(PBVScrnTxtAttr \ &H10)  ' BOZOCOLORs, in case they change.
  285. ' Now make one pass and DRAW the fields on the screen with defaults
  286. DO UNTIL DBE(Fld%).FieldLength=0
  287.     BOZOLOCATE DBE(Fld%).FieldRow,DBE(Fld%).FieldCol
  288.         BOZOCOLOR of%,ob%
  289.         BOZOPRINT RTRIM$(DBE(Fld%).FieldName,chr$(0))+":"
  290.      X%=BOZOCSRLIN:Y%=BOZOPOS
  291.         BOZOCOLOR DBE(Fld%).FieldFG,DBE(Fld%).FieldBG
  292.         BOZOPRINT SPACE$(DBE(Fld%).FieldLength)
  293.     X%=BOZOCSRLIN:Y%=BOZOPOS
  294.         IF DBE(Fld%).FieldType="N" THEN
  295.             BOZOPRINT LTRIM$(STR$(dBGetNField!((DBE(Fld%).FieldName),E%)))
  296.                 IF E% THEN BOZOPRINT "???"
  297.     ELSE
  298.             BOZOPRINT dBGetCField$((DBE(Fld%).FieldName),E%)
  299.                 IF E% THEN BOZOPRINT "???"
  300.     END IF
  301.  
  302.     INCR Fld%
  303. LOOP
  304.  
  305.  
  306. Fld%=1 ' start with the first field on the screen
  307. ' Now go back and edit the fields
  308. DO UNTIL DBE(Fld%).FieldLength=0
  309.     BOZOLOCATE DBE(Fld%).FieldRow,DBE(Fld%).FieldCol
  310.         BOZOCOLOR of%,ob%
  311.         BOZOPRINT RTRIM$(DBE(Fld%).FieldName,CHR$(0))+":"
  312.         r%=BOZOCSRLIN:C%=BOZOPOS
  313.         IF DBE(Fld%).FieldType="N" THEN
  314.                 num%=-1
  315.             ED$=LTRIM$(STR$(dBGetNField!((DBE(Fld%).FieldName),E%)))
  316.                 IF E% THEN ED$="???"
  317.                     ELSE
  318.                 num%=0
  319.             ED$= dBGetCField$((DBE(Fld%).FieldName),E%)
  320.                 IF E% THEN ED$="???"
  321.     END IF
  322.  
  323.         ED$=DBGET$(r%, c%, (DBE(Fld%).FieldLength), (DBE(Fld%).FieldFG),_
  324.                   (DBE(Fld%).FieldBG), ED$, -1, num%,KeyFlag%)
  325.  
  326.         IF num% THEN
  327.             dBPutNField (DBE(Fld%).FieldName), VAL(ED$), E%
  328.         ELSE
  329.             dBPutCField (DBE(Fld%).FieldName),ED$,E%
  330.     END IF
  331.  
  332.     SELECT CASE KeyFlag%
  333.             CASE 10
  334.                     DBPutRecord RecNum???, E%
  335.                         EXIT LOOP
  336.         CASE 5
  337.                     EXIT LOOP
  338.         CASE 0,2,6
  339.                     INCR Fld%
  340.                         IF Fld%>NumberOfFields? THEN
  341.                             DBPutRecord RecNum???,e%
  342.                                 EXIT LOOP
  343.                                 END IF
  344.                                 'Fld%=NumberOfFields?
  345.                 CASE 4,8
  346.                     DECR Fld%
  347.                         IF Fld%=0 THEN Fld%=1
  348.         END SELECT
  349. LOOP
  350. BOZOCOLOR Of%, Ob%
  351.  
  352. END SUB
  353.  
  354.  
  355.  
  356. SUB dBPutCField(FieldName$, FieldData$, Ecode%)
  357. Ecode% = 1
  358.     FieldName$=UCASE$(FieldName$)
  359. FOR nof? = 1 TO NumberOfFields?
  360.     IF LEFT$(DBS(nof?).FieldName,LEN(FieldName$)) = FieldName$ THEN
  361.                 IF LEN(FieldData$)>DBS(nof?).FieldLength THEN FieldData$=LEFT$(FieldData$,DBS(nof?).FieldLength)
  362.         MID$(RecordBlock$, DBS(nof?).Fieldoffset,_
  363.         DBS(nof?).FieldLength) = FieldData$ + _
  364.                 Space$(DBS(nof?).FieldLength-LEN(FieldData$))
  365.         Ecode% = 0
  366.         EXIT FOR
  367.     END IF
  368. NEXT nof?
  369. END SUB
  370.  
  371. SUB dBPutNField(FieldName$, FieldData!, Ecode%)
  372.     Ecode% = 1
  373.     FieldName$=UCASE$(FieldName$)
  374.  
  375. FOR nof? = 1 TO NumberOfFields?
  376.     IF LEFT$(DBS(nof?).FieldName,LEN(FieldName$)) = FieldName$ THEN
  377.     Pattern$ = STRING$(DBS(nof?).FieldLength,"#")
  378.     IF DBS(nof?).FieldDecimals > 0 THEN
  379.     MID$(Pattern$,LEN(Pattern$)-(DBS(nof?).FieldDecimals),1)="."
  380.     END IF
  381.     FieldData$ = USING$(Pattern$,FieldData!)
  382.     MID$(RecordBlock$, DBS(nof?).Fieldoffset,_
  383.     DBS(nof?).FieldLength) = FieldData$
  384.         Ecode% = 0
  385.         EXIT FOR
  386.     END IF
  387. NEXT nof?
  388.  
  389. END SUB
  390.  
  391.  
  392. SUB dBPutRecord(RN???,Ecode%)
  393. Ecode% = 0
  394. IF dBaseOpen% = 0 THEN Ecode% = 1: Exit Sub
  395.                          ' Error Code 1 = Database file not open
  396. GET #dBaseOpen%, 1, DBH
  397. IF RN??? > DBH.NumberOfRecords + 1 THEN RN???=0
  398. IF RN???<1 OR RN???=DBH.NumberOfRecords+1 THEN RN???=DBH.NumberOfRecords+1 :_
  399.  DBH.NumberOfRecords = RN???:LastRec%=1: NumberOfRecords???=RN???
  400. R$=MID$(RecordBlock$,2)
  401. IF LEN(R$)<DBH.Size+1 THEN R$=R$+SPACE$(DBH.Size+1-LEN(R$))
  402. IF LastRec%=1 THEN R$=R$+CHR$(26)
  403. PUT #dBaseOpen%, DBH.offset + ((RN??? * DBH.Size) - DBH.Size)+1 , R$
  404. IF DBH.NumberOfRecords = RN??? THEN _
  405.           e$ = CHR$(26) + CHR$(10): PUT #dBaseOpen%, SEEK(dBaseOpen%) + 1, e$
  406. DBH.Day   = VAL(MID$(DATE$, 4, 2))
  407. DBH.Month = VAL(LEFT$(DATE$, 2))
  408. DBH.Year  = VAL(RIGHT$(DATE$, 2))
  409.  
  410. PUT #dBaseOpen%, 1, DBH
  411. RecNum???=RN???
  412. END SUB
  413.  
  414.  
  415. SUB dBGetARRAY(DB$(),Ecode%)
  416.  
  417. IF UBOUND(DB$()) < NumberOfFields? THEN Ecode% = 1:EXIT SUB
  418.                     ' Error code 1, array not big enough
  419. FOR nof? = 1 TO NumberOfFields?
  420.     IF INSTR("CLD",DBS(nof?).FieldType) THEN
  421.         DB$(nof?) = MID$(RecordBlock$, DBS(nof?).Fieldoffset,_
  422.         DBS(nof?).FieldLength)
  423.     ELSE
  424.         DB$(nof?) = STR$(val(MID$(RecordBlock$, DBS(nof?).Fieldoffset,_
  425.      DBS(nof?).FieldLength)) * (10 ^ DBS(nof?).FieldDecimals))
  426.     END IF
  427. NEXT nof?
  428. END SUB
  429.  
  430.  
  431.  
  432. FUNCTION dBGetASCII$
  433. A$=""
  434. FOR nof? = 1 TO NumberOfFields?
  435.     IF INSTR("CLD",DBS(nof?).FieldType) THEN
  436.         A$ = A$ + CHR$(34)+MID$(RecordBlock$, DBS(nof?).Fieldoffset,_
  437.         DBS(nof?).FieldLength)+CHR$(34)
  438.     ELSE
  439.         A$ = A$ + STR$(val(MID$(RecordBlock$, DBS(nof?).Fieldoffset,_
  440.      DBS(nof?).FieldLength)) * (10 ^ DBS(nof?).FieldDecimals))
  441.     END IF
  442.     IF nof? < NumberOfFields? THEN A$ = A$ + ","
  443. NEXT nof?
  444. dBGetASCII$ = A$
  445. END FUNCTION
  446.  
  447.  
  448.  
  449.  
  450. FUNCTION dBGetCField$ (FieldName$, Ecode%)
  451. Ecode% = 1
  452.     FieldName$=UCASE$(FieldName$)
  453. FOR nof? = 1 TO NumberOfFields?
  454.     IF LEFT$(DBS(nof?).FieldName,LEN(FieldName$)) = FieldName$ THEN
  455.         dBGetCField$ = MID$(RecordBlock$, DBS(nof?).Fieldoffset,_
  456.         DBS(nof?).FieldLength)
  457.         Ecode% = 0
  458.         EXIT FOR
  459.     END IF
  460. NEXT nof?
  461. END FUNCTION
  462.  
  463. FUNCTION dBGetNField!(FieldName$,Ecode%)
  464.     Ecode% = 1
  465.     FieldName$=UCASE$(FieldName$)
  466. FOR nof? = 1 TO NumberOfFields?
  467.     IF LEFT$(DBS(nof?).FieldName,LEN(FieldName$)) = FieldName$ THEN
  468.     dBGetNField! = val(MID$(RecordBlock$, DBS(nof?).Fieldoffset,_
  469.      DBS(nof?).FieldLength)) '* (10 ^ -DBS(nof?).FieldDecimals)
  470.         Ecode% = 0
  471.         EXIT FOR
  472.     END IF
  473. NEXT nof?
  474.  
  475. END FUNCTION
  476.  
  477.  
  478. SUB DBGetRecord (Rn???, Ecode%)
  479. Ecode% = 0
  480. IF dBaseOpen% = 0 THEN Ecode% = 1: EXIT SUB              ' database not open
  481. GET #dBaseOpen%, 1, DBH
  482. IF Rn??? > DBH.NumberOfRecords THEN Ecode% = 2: EXIT SUB   ' record too high
  483. IF Rn??? < 1 THEN Ecode% = 2: EXIT SUB                     ' record too low
  484.  
  485. SEEK #dBaseOpen%, DBH.offset + (Rn??? * DBH.Size) - DBH.Size
  486. GET$ dBaseOpen%, DBH.Size + 2, RecordBlock$
  487. RecNum???=RN???
  488. END SUB  ' dBGetRecord
  489.  
  490.  
  491.  
  492. SUB dBUse (FileName$, Ecode%)
  493. Ecode% = 0: Recnum??? = 0
  494. IF dBaseOpen% THEN CLOSE #dBaseOpen%: dBaseOpen% = 0
  495.                                   'if database file is open, then close it.
  496. FileName$ = UCASE$(FileName$)
  497. IF INSTR(FileName$, ".") = 0 THEN FileName$ = FileName$ + ".DBF"
  498. IF DIR$(FileName$) = "" THEN Ecode% = 1: EXIT SUB
  499.                                                   ' error 1=file not found
  500.  
  501. LET dBaseOpen% = 81
  502. OPEN FileName$ FOR BINARY ACCESS READ WRITE SHARED AS #dBaseOpen%
  503. IF LOF(dBaseOpen%) = 0 THEN CLOSE #dBaseOpen%:dBaseOpen%=0:Ecode%=2:EXIT SUB
  504.                                                 ' Error 2=file is 0 length
  505.  
  506. GET #dBaseOpen%, 1, DBH
  507. IF DBH.Year > 99 OR DBH.Month > 12 OR DBH.Month = 0 OR_
  508.    DBH.Day > 31 OR DBH.Day = 0 THEN CLOSE #dBaseOpen%:_
  509.    dBaseOpen% = 0: Ecode% = 4: EXIT SUB
  510.                                               ' Error 4 = not a dBASE file
  511.  
  512. ' establish number of fields by (dbh.offset-len(dbheader))\32
  513. NumberOfRecords??? = DBH.NumberOfRecords
  514. NumberOfFields? = (DBH.offset - LEN(DBH)) \ 32
  515. IF NumberOfFields?<1 THEN Ecode% = 3:CLOSE #dBaseOpen%:dBaseOpen%=0:Exit SUB
  516.                                 ' Error 3 = no fields in database structure
  517.  
  518.  
  519. ' Load the field definition header
  520. DBS(1).FieldOffset = 3
  521. FOR nof? = 1 TO NumberOfFields?
  522.     GET #dBaseOpen%, SEEK(dBaseOpen%), DBF
  523.  
  524.         DBS(nof?).FieldName     = DBF.FieldName
  525.         DBS(nof?).FieldType     = DBF.FieldType
  526.         DBS(nof?).FieldLength   = DBF.FLen
  527.         DBS(nof?+1).FieldOffset = DBS(nof?).FieldOffset + DBF.FLen
  528.         DBS(nof?).FieldDecimals = DBF.DecC
  529. NEXT nof?
  530. CALL dBDefaultFormat  ' set default screen format
  531. RecordBlock$=SPACE$(DBH.Size+2)
  532. END SUB 'dBUse
  533.  
  534.  
  535. FUNCTION DBGET$(y%,x%,length%,fg%,bg%,whole$,ins%,num%,keyflag%)
  536. LOCAL tscan%, xitflag%, curpos%, tempwhole$, first%
  537.   ofg%=(PBVSCRNTXTATTR AND &HF)
  538.   ofb%=PBVSCRNTXTATTR / &H10
  539.   keyflag% = 0
  540.   tempwhole$ = whole$
  541.   first% = %TRUE
  542.   BOZOLOCATE y%,x%
  543.   BOZOCOLOR fg%,bg% : BOZOPRINT SPACE$(length%)
  544.   xitflag% = %FALSE
  545.   curpos% = 0
  546.  
  547.   DO
  548.     'IF ins% THEN tscan% = %INSERTSCAN ELSE tascn% = %OVERWRITESCAN
  549.         IF LEN(Whole$)>Length% THEN WHOLE$=LEFT$(Whole$,Length%)
  550.         IF LEN(Whole$)<Length% THEN WHOLE$=WHOLE$+SPACE$(Length%=LEN(Whole$))
  551.     BOZOLOCATE y%,x% : BOZOPRINT whole$
  552.     BOZOLOCATE y%,x%+curpos%
  553.  
  554.     ky$ = GETKEY$("")
  555.     IF ky$ < CHR$(31) THEN first% = %FALSE
  556.     SELECT CASE ky$
  557.       CASE > CHR$(31)
  558.         IF num% THEN
  559.           IF ky$ > CHR$(62) THEN EXIT SELECT
  560.         END IF
  561.         IF first% THEN
  562.           whole$ = ky$
  563.           curpos% = 1
  564.           first% = %FALSE
  565.           EXIT SELECT
  566.         END IF
  567.         IF ins% THEN
  568.           IF curpos% < LEN(whole$) THEN
  569.             whole$ = RTRIM$(whole$)
  570.             IF LEN(whole$) < length% THEN
  571.               whole$ = LEFT$(whole$,curpos%)+ky$+RIGHT$(whole$,LEN(whole$)-curpos%)
  572.               INCR curpos%,1
  573.               IF curpos% = length% THEN DECR curpos%,1
  574.             END IF
  575.           ELSE
  576.             whole$ = whole$ + ky$
  577.             INCR curpos%,1
  578.             IF curpos% = length% THEN DECR curpos%,1
  579.           END IF
  580.         ELSE
  581.           IF curpos% < LEN(whole$) THEN
  582.             MID$(whole$,curpos%+1) = ky$
  583.           ELSE
  584.             whole$ = whole$ + ky$
  585.           END IF
  586.           INCR curpos%,1
  587.           IF curpos% = length% THEN DECR curpos%,1
  588.         END IF
  589.       CASE CHR$(0,75) '**** LEFT ****
  590.         IF curpos% <> 0 THEN DECR curpos%,1
  591.       CASE CHR$(0,77)'**** RIGHT ****
  592.         IF curpos% <> length%-1 THEN INCR curpos%,1
  593.         IF curpos% > LEN(whole$) THEN whole$=whole$+" "
  594.       CASE CHR$(0,71)'**** HOME ****
  595.         curpos% = 0
  596.       CASE CHR$(0,79)'**** END ****
  597.            whole$ = RTRIM$(whole$)
  598.            curpos% = LEN(whole$)
  599.            IF LEN(whole$) = length% THEN DECR curpos%,1
  600.       CASE CHR$(0,82)'**** INS ****
  601.         ins% = NOT ins%
  602.         IF tscan% = 3 THEN tscan% = 6 ELSE tscan% = 3
  603.       CASE CHR$(0,83)'**** DEL ****
  604.         IF curpos% > LEN(whole$)-1 THEN EXIT SELECT
  605.         whole$ = LEFT$(whole$,curpos%) + RIGHT$(whole$,LEN(whole$)-curpos%-1)
  606.       CASE CHR$(8)'**** BACKSPACE ****
  607.         IF curpos% <> 0 THEN
  608.           whole$ = LEFT$(whole$,curpos%-1) + RIGHT$(whole$,LEN(whole$)-curpos%)
  609.           DECR curpos%,1
  610.         END IF
  611.       CASE CHR$(13)'**** ENTER ****
  612.         xitflag% = %TRUE
  613.         keyflag% = 0
  614.       CASE CHR$(27)'**** ESC ****
  615.         xitflag% = %TRUE
  616.         keyflag% = 5
  617.         whole$ = tempwhole$
  618.       CASE CHR$(0,72)'**** UP ARROW ****
  619.         xitflag% = %TRUE
  620.         keyflag% = 8
  621.       CASE CHR$(0,80)'**** DOWN ARROW ****
  622.         xitflag% = %TRUE
  623.         keyflag% = 2
  624.       CASE CHR$(9)'**** TAB ****
  625.         xitflag% = %TRUE
  626.         keyflag% = 6
  627.       CASE CHR$(0,15)'**** SHFT-TAB ****
  628.         xitflag% = %TRUE
  629.         keyflag% = 4
  630.           CASE CHR$(0,117),CHR$(0,68),CHR$(14)
  631.               xitflag%=%TRUE
  632.                 keyflag%=10
  633.  
  634.     END SELECT
  635.  
  636.   LOOP UNTIL xitflag%
  637.   BOZOCOLOR ofg%, obg%
  638.   DBGET$ = RTRIM$(whole$)
  639.  
  640. END FUNCTION
  641.  
  642. FUNCTION getkey$(mstr$)
  643.   IF mstr$ = "" THEN
  644.     DO
  645.       IF INSTAT THEN k$=INKEY$ ELSE k$ = BOZOINKEY$:IF K$=CHR$(27) THEN GOSUB K.Arrow
  646.     LOOP UNTIL k$ <> ""
  647.   ELSE
  648.     DO
  649.      IF INSTAT THEN k$ = INKEY$ ELSE k$=BOZOINKEY$:IF K$=CHR$(27) THEN GOSUB K.ARROW
  650.     LOOP UNTIL INSTR(k$,ANY mstr$)
  651.   END IF
  652. GOTO EndGetKeyFunction
  653.  
  654. K.ARROW:
  655. DELAY .25
  656.     IF COMCHARS% THEN K$=K$+COMCHAR$ ELSE RETURN
  657.         IF INSTR(K$,"A") THEN K$=CHR$(0,72)
  658.         IF INSTR(K$,"B") THEN K$=CHR$(0,80)
  659.         IF INSTR(K$,"C") THEN K$=CHR$(0,75)
  660.         IF INSTR(K$,"D") THEN K$=CHR$(0,77)
  661. RETURN
  662.  
  663.  
  664. EndGetKeyFunction:
  665.   getkey$ = k$
  666. END FUNCTION
  667.  
  668. SUB DBSCRNFIND(X%, Y%, F$)
  669. IF ComLine THEN BOZOPRINT "Cannot design screens while on-line"+CrLf$:EXIT SUB
  670. 'arrows around F$ on the screen. and returns the ultimate coordinates.
  671. REG 1, 15*256
  672. CALL INTERRUPT &H10
  673. IF Reg(1) - (Reg(1)\256) * 256 = 7 THEN Address=&HB000 else Address=&HB800
  674. DEF SEG = ADDRESS
  675. O$=PEEK$(0,4000)
  676.  
  677. DO   ' a deer, a female deer
  678.     LOCATE X%, Y%:COLOR 20,0:PRINT F$;
  679.         COLOR 7,0
  680.         LOCATE 23,1:PRINT SPACE$(80);
  681.         LOCATE 23,1:PRINT "Use arrows to re-position field.  ENTER finishes, ESC aborts.";
  682.     KB$="" : WHILE KB$=""    ' create a polling loop instead of SLEEPing
  683.                 KB$=INKEY$
  684.         WEND
  685.         POKE$ 0,O$
  686.         SELECT CASE KB$
  687.  
  688.             CASE CHR$(0,71) '  home
  689.                             Y%=1
  690.             CASE CHR$(0,72) '  up arrow
  691.                             DECR X%:IF X%=0 THEN X%=22
  692.             CASE CHR$(0,73) '  page up
  693.                             X%=1
  694.             CASE CHR$(0,75) '  left arrow
  695.                             DECR Y%:IF Y%=0 THEN Y%=79-LEN(F$)
  696.             CASE CHR$(0,77) '  right arrow
  697.                             INCR Y%:IF Y%>79-LEN(F$) THEN Y%=1
  698.             CASE CHR$(0,79) '  end
  699.                             Y%=79-LEN(F$)
  700.             CASE CHR$(0,80) '  down arrow
  701.                             INCR X%:IF X%=23 THEN X%=1
  702.             CASE CHR$(0,81) '  page down
  703.                             X%=22
  704.             CASE CHR$(0,82) '  Insert
  705.             CASE CHR$(0,83) '  Delete
  706.             CASE CHR$(0,59) '  f1
  707.             CASE CHR$(0,60) '  f2
  708.             CASE CHR$(0,61) '  f3
  709.             CASE CHR$(0,62) '  f4
  710.             CASE CHR$(0,63) '  f5
  711.             CASE CHR$(0,64) '  f6
  712.             CASE CHR$(0,65) '  f7
  713.             CASE CHR$(0,66) '  f8
  714.             CASE CHR$(0,67) '  f9
  715.             CASE CHR$(0,68) '  f10
  716.                             FINISHED=-1
  717.             CASE CHR$(0,115) ' CTL-Left arrow
  718.                             Y%=Y%-8:IF Y%<1 THEN Y%=1
  719.             CASE CHR$(0,116) ' CTL-Right arrow
  720.                             Y%=Y%+8:IF Y%>79-LEN(F$) THEN y%=79-LEN(F$)
  721.             CASE CHR$(0,117) ' CTL-END
  722.                             FINISHED=-1
  723.             CASE CHR$(0,118) ' CTL-PgDn
  724.             CASE CHR$(0,119) ' CTL-HOME
  725.                             X%=1:Y%=1
  726.             CASE CHR$(0,132) ' CTL-PgUp
  727.             CASE CHR$(3)  '  CTL-C ETX
  728.                             X%=0:FINISHED=-1
  729.             CASE CHR$(9)  '  CTL-I TAB
  730.                             Y%=Y%+8:IF Y%>79-LEN(F$) THEN y%=79-LEN(F$)
  731.             CASE CHR$(13)  ' CTL-M CARRIAGE RETURN
  732.                             FINISHED=-1
  733.             CASE CHR$(16)  ' CTL-P DLE
  734.             CASE CHR$(21)  ' CTL-U NAK
  735.             CASE CHR$(27)  ' Escape ESC
  736.                             X%=0:FINISHED=-1
  737.  
  738.             END SELECT
  739.  
  740.  
  741. LOOP WHILE NOT FINISHED
  742. POKE$ 0, O$
  743. DEF SEG
  744.  
  745. END SUB
  746.  
  747.