ADDRBOOK.MOD 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. MODULE AddrBook;
  2. (*
  3. * ModBase
  4. * Release 3.0
  5. * (c) Copyright 1986 - 1990 Donald G. Fletcher
  6. * (c) Copyright 1986 - 1990 PMI
  7. * P.O. Box 8402
  8. * Green Bay Wi 53308
  9. * All Rights Reserved
  10. *)
  11. (* IMPORT PMD;*)
  12. IMPORT DBIndxes;
  13. IMPORT DspFiles;
  14. IMPORT ErrorManager;
  15. IMPORT HandleIO;
  16. IMPORT KbdInput;
  17. IMPORT LowLevel;
  18. IMPORT M2Strings;
  19. IMPORT ModBase3;
  20. IMPORT MsColors;
  21. IMPORT PosUtils;
  22. IMPORT ScreenDisplay;
  23. IMPORT ScreenInput;
  24. IMPORT Scrn2DBF;
  25. IMPORT ScrnTypes;
  26. IMPORT SmartScreen;
  27. IMPORT StrConv;
  28. IMPORT StrEdit;
  29. IMPORT StringIO;
  30. IMPORT SYSTEM;
  31. IMPORT UserOps;
  32. IMPORT VWindows;
  33. IMPORT WindowPrims;
  34. IMPORT InitCompilerMods;
  35. VAR
  36. DataFile: ModBase3.DBFile;
  37. IndexByName: DBIndxes.DBIndex;
  38. ScreenFile : ScrnTypes.DisplayFile;
  39. SavedCursorHeight : CARDINAL;
  40. PROCEDURE Confirm(query: ARRAY OF CHAR): BOOLEAN;
  41. VAR
  42. KeyHit: CARDINAL;
  43. BEGIN
  44. WindowPrims.MsgBox( VWindows.SE, query,
  45. KbdInput.YorN, KeyHit );
  46. RETURN KbdInput.CAPkey( KeyHit ) = ORD('Y');
  47. END Confirm;
  48. PROCEDURE ChangeExtension(VAR name: ARRAY OF CHAR; ext: ARRAY OF CHAR);
  49. VAR
  50. i, j: CARDINAL;
  51. BEGIN
  52. i := 0;
  53. StrEdit.CrunchBlanks(name);
  54. LOOP
  55. IF (i > HIGH(name)) OR (name[i] = 0C) OR (name[i] = '.') THEN
  56. EXIT
  57. END;
  58. INC(i);
  59. END; (* LOOP *)
  60. IF i <= (HIGH(name)) THEN
  61. name[i] := '.';
  62. INC(i);
  63. FOR j := 0 TO 2 DO
  64. IF i <= HIGH(name) THEN
  65. name[i] := ext[j];
  66. INC(i);
  67. END;
  68. END;
  69. END;
  70. END ChangeExtension;
  71. PROCEDURE GetNewDbFile( VAR TheDbFile: ModBase3.DBFile; VAR TheDbIndex:
  72. DBIndxes.DBIndex; TheName: ARRAY OF CHAR ): BOOLEAN;
  73. VAR
  74. temp: ARRAY [1..8] OF ModBase3.DBFieldDescriptor;
  75. TmpStr: ARRAY [0..255] OF CHAR;
  76. IndexOpened : BOOLEAN;
  77. BEGIN
  78. IF ModBase3.Initialized(TheDbFile) THEN
  79. ModBase3.CloseDBF( TheDbFile );
  80. ModBase3.DisposeDBF(TheDbFile);
  81. DBIndxes.CloseIndex( TheDbIndex );
  82. DBIndxes.DisposeIndex(TheDbIndex );
  83. END;
  84. ChangeExtension( TheName, 'dbf');
  85. IndexOpened := FALSE;
  86. ModBase3.InitDBF( TheName, TheDbFile, 0, TRUE ,FALSE,TRUE,ModBase3.DefaultFixUp);
  87. IF NOT ModBase3.OpenDBF( TheDbFile ) THEN
  88. StrEdit.AssignStr(
  89. 'File not found. Create a new file named ', TmpStr );
  90. StrEdit.Append( TmpStr, TheName );
  91. StrEdit.CutTrailingChars( ' ', TmpStr );
  92. StrEdit.Append( TmpStr, '? (Y/N)' );
  93. IF Confirm( TmpStr ) THEN
  94. temp[1].name := 'NAME';
  95. temp[1].size := 30;
  96. temp[1].fldtype := 'C';
  97. temp[2].name := 'COMPANY';
  98. temp[2].size := 30;
  99. temp[2].fldtype := 'C';
  100. temp[3].name := 'ADDRESS1';
  101. temp[3].size := 30;
  102. temp[3].fldtype := 'C';
  103. temp[4].name := 'ADDRESS2';
  104. temp[4].size := 30;
  105. temp[4].fldtype := 'C';
  106. temp[5].name := 'CITY';
  107. temp[5].size := 20;
  108. temp[5].fldtype := 'C';
  109. temp[6].name := 'STATE';
  110. temp[6].size := 2;
  111. temp[6].fldtype := 'C';
  112. temp[7].name := 'ZIPCODE';
  113. temp[7].size := 10;
  114. temp[7].fldtype := 'C';
  115. temp[8].name := 'ASKDATE';
  116. temp[8].size := 8;
  117. temp[8].fldtype := 'C';
  118. StringIO.PrintMessage(ModBase3.BuildDBF( temp, 8, TheDbFile ));
  119. END;
  120. END;
  121. ChangeExtension(TheName, 'NUM');
  122. IF ModBase3.OpenDBF(TheDbFile) THEN
  123. IF HandleIO.FileExists( TheName ) THEN
  124. DBIndxes.InitIndex(TheName, TheDbIndex,TheDbFile, 5, TRUE,TRUE,FALSE);
  125. IndexOpened := DBIndxes.OpenIndex(TheDbIndex);
  126. ELSE
  127. DBIndxes.InitIndex(TheName, TheDbIndex, TheDbFile, 5, TRUE,TRUE,FALSE);
  128. StringIO.PrintMessage(DBIndxes.BuildIndex(TheDbIndex, 'NAME'));
  129. IndexOpened := DBIndxes.OpenIndex(TheDbIndex);
  130. END;
  131. END;
  132. RETURN (*TheDbFile.open AND*) IndexOpened;
  133. END GetNewDbFile;
  134. PROCEDURE ProcessNumberedRecord( RecordNumber: LONGINT;
  135. NewRecord: BOOLEAN; NameIfNew: ARRAY OF CHAR ): ScrnTypes.FrameKey;
  136. VAR
  137. NxtFrame: ScrnTypes.FrameKey;
  138. TheCount: CARDINAL;
  139. BEGIN
  140. IF (RecordNumber >ModBase3.NumberRecords(DataFile)) THEN
  141. IF NOT NewRecord THEN
  142. RETURN 2;
  143. END;
  144. END;
  145. ScreenDisplay.ReadDisplayFrame( ScreenFile,
  146. DspFiles.MainFrame, 4 );
  147. (* The data input frame. *)
  148. IF NOT NewRecord THEN
  149. ModBase3.ReadDBRec( DataFile, RecordNumber );
  150. IF ModBase3.Deleted( DataFile ) THEN
  151. RETURN 2;
  152. END;
  153. Scrn2DBF.DBFToFrame( DataFile, DspFiles.MainFrame );
  154. ELSE
  155. ScreenInput.ChangeField( DspFiles.MainFrame,
  156. NameIfNew, 'NAME', TRUE );
  157. END;
  158. REPEAT
  159. (* MainFrame should always have frame 4, the input frame,
  160. in it at this point. *)
  161. ScreenDisplay.ShowDisplayFrame( DspFiles.MainFrame,
  162. 0, 0, 0, 0 );
  163. ScreenDisplay.PushFrame( DspFiles.MainFrame );
  164. (* This saves the contents of the input frame until we
  165. are ready to Edit it or write it to the DataFile. *)
  166. NxtFrame := 3; (* The Edit/Save/Delete/Return menu. *)
  167. ScreenInput.Input( NxtFrame );
  168. CASE NxtFrame OF
  169. 4: (* User wants to Edit record. *)
  170. ScreenDisplay.PopFrame( DspFiles.MainFrame );
  171. (* Pop frame 3 off MainFrame's frame stack,
  172. bringing frame 4 back to the top. *)
  173. NxtFrame := ScreenInput.ControlFrame(
  174. DspFiles.MainFrame, 0, '', FALSE );
  175. | 9: (*Save*)
  176. ScreenDisplay.PopFrame( DspFiles.MainFrame );
  177. (* Brings the input frame back to the top of
  178. MainFrame's frame stack. *)
  179. IF NewRecord THEN
  180. ModBase3.AppendBlank( DataFile );
  181. END;
  182. IF NOT Scrn2DBF.FrameToDBF( DataFile,
  183. DspFiles.MainFrame) THEN
  184. IF NOT Confirm( 'Error writing record. Continue?' ) THEN
  185. HALT;
  186. END;
  187. END;
  188. ModBase3.WriteDBRec( DataFile );
  189. IF NOT NewRecord THEN
  190. DBIndxes.DeleteCurrentEntry( IndexByName );
  191. ELSE
  192. NewRecord := FALSE;
  193. END;
  194. DBIndxes.AddRecord( DataFile, IndexByName );
  195. ScreenDisplay.PushFrame( DspFiles.MainFrame );
  196. (* We're going to be pushing MainFrame at the top
  197. of the next loop, so we save and restore it
  198. here. *)
  199. ScreenInput.Input( NxtFrame ); (* success message *)
  200. ScreenDisplay.PopFrame( DspFiles.MainFrame );
  201. | 10: (*Delete*)
  202. ScreenDisplay.PopFrame( DspFiles.MainFrame );
  203. IF NOT NewRecord THEN
  204. ModBase3.DeleteRecord( DataFile );
  205. DBIndxes.DeleteCurrentEntry( IndexByName );
  206. END;
  207. NewRecord := TRUE;
  208. ScreenDisplay.PushFrame( DspFiles.MainFrame );
  209. ScreenInput.Input( NxtFrame ); (* success message *)
  210. ScreenDisplay.PopFrame( DspFiles.MainFrame );
  211. | 2: (*Return*)
  212. ScreenDisplay.PopFrame( DspFiles.MainFrame );
  213. END;
  214. UNTIL (NxtFrame = 2);
  215. RETURN NxtFrame;
  216. END ProcessNumberedRecord;
  217. PROCEDURE ProcessNamedRecord( RecordName: ARRAY OF CHAR; VAR
  218. RecordNumber: LONGINT ): ScrnTypes.FrameKey;
  219. VAR
  220. found: BOOLEAN;
  221. BEGIN
  222. IF PosUtils.IsBlank( RecordName ) THEN
  223. RETURN 2;
  224. END;
  225. DBIndxes.FindPositionCh( IndexByName, RecordName, found );
  226. IF (NOT found) AND
  227. (NOT Confirm( 'Record not found. Create it? (Y/N)' )) THEN
  228. RETURN 2;
  229. END;
  230. RecordNumber := DBIndxes.CurrentRec( IndexByName );
  231. ScreenDisplay.ReadDisplayFrame( ScreenFile,
  232. DspFiles.MainFrame, 4 );
  233. (* Reads the data input frame from disk into MainFrame. *)
  234. RETURN ProcessNumberedRecord( RecordNumber, NOT found, RecordName );
  235. END ProcessNamedRecord;
  236. PROCEDURE ImportFromAscii( VAR TheDbFile: ModBase3.DBFile; VAR
  237. TheIndexFile: DBIndxes.DBIndex; AsciiFileName: ARRAY OF CHAR ):
  238. BOOLEAN;
  239. (*Assumes the ascii file contains fixed-length records, each
  240. on a single CR/LF-terminated line. *)
  241. VAR
  242. FieldCnt, FileHandle: CARDINAL;
  243. CheckStr: ARRAY [0..1] OF CHAR;
  244. fpt:ModBase3.DBFieldPtr;
  245. BEGIN
  246. IF NOT (HandleIO.OpenFile( FileHandle, AsciiFileName) =
  247. StringIO.NoError) THEN
  248. RETURN FALSE;
  249. END;
  250. fpt:= ModBase3.FieldList(TheDbFile);
  251. LOOP
  252. ModBase3.AppendBlank( TheDbFile );
  253. FieldCnt := 1;
  254. REPEAT
  255. IF NOT (HandleIO.BlockRead( FileHandle,
  256. LowLevel.AddAddr(ModBase3.RecordPtr(TheDbFile),
  257. fpt^[FieldCnt].offset - 1),
  258. fpt^[FieldCnt].size ) =
  259. StringIO.NoError) THEN
  260. EXIT;
  261. END;
  262. INC( FieldCnt );
  263. UNTIL FieldCnt > ModBase3.NumberOfFields(TheDbFile);
  264. IF NOT (HandleIO.BlockRead( FileHandle,
  265. SYSTEM.ADR(CheckStr), 2 ) = StringIO.NoError) THEN
  266. (*Read what should be the CR/LF.*)
  267. EXIT;
  268. END;
  269. IF M2Strings.CompareStr( CheckStr, StringIO.CrLf ) # 0 THEN
  270. EXIT;
  271. (* We exit here instead of returning false to make sure
  272. the FileHandle is closed. *)
  273. END;
  274. ModBase3.WriteDBRec( TheDbFile );
  275. DBIndxes.AddRecord( TheDbFile, TheIndexFile );
  276. IF HandleIO.EndReached( FileHandle ) THEN
  277. EXIT;
  278. END;
  279. END;
  280. IF (HandleIO.CloseHandle( FileHandle ) = StringIO.NoError) THEN
  281. RETURN TRUE;
  282. ELSE
  283. RETURN FALSE;
  284. END;
  285. END ImportFromAscii;
  286. PROCEDURE ExportToAscii( VAR TheDbFile: ModBase3.DBFile; AsciiFileName:
  287. ARRAY OF CHAR );
  288. VAR
  289. FieldCnt, FileHandle: CARDINAL;
  290. RecordNumber: LONGINT;
  291. fpt:ModBase3.DBFieldPtr;
  292. BEGIN
  293. IF NOT (HandleIO.CreateFile( FileHandle, AsciiFileName ) =
  294. StringIO.NoError) THEN
  295. RETURN;
  296. END;
  297. fpt:= ModBase3.FieldList(TheDbFile);
  298. RecordNumber := VAL(LONGINT, 0);
  299. LOOP
  300. INC( RecordNumber );
  301. IF (RecordNumber > ModBase3.NumberRecords(TheDbFile)) THEN
  302. EXIT;
  303. END;
  304. ModBase3.ReadDBRec( TheDbFile, RecordNumber );
  305. IF NOT ModBase3.Deleted( TheDbFile ) THEN
  306. (* skip records that have been marked for deletion *)
  307. FieldCnt := 1;
  308. REPEAT
  309. IF NOT (HandleIO.BlockWrite( FileHandle,
  310. LowLevel.AddAddr(ModBase3.RecordPtr(TheDbFile),
  311. fpt^[FieldCnt].offset - 1),
  312. fpt^[FieldCnt].size ) =
  313. StringIO.NoError) THEN
  314. EXIT;
  315. END;
  316. INC( FieldCnt );
  317. UNTIL FieldCnt > ModBase3.NumberOfFields(TheDbFile);
  318. StringIO.WriteEol( FileHandle, '' );
  319. END;
  320. END;
  321. StringIO.PrintMessage( HandleIO.CloseHandle( FileHandle ) );
  322. END ExportToAscii;
  323. PROCEDURE RestoreDisplay();
  324. BEGIN
  325. VWindows.SetForeColor( VWindows.CurrentWindow, MsColors.lightgrey );
  326. VWindows.SetBackColor( VWindows.CurrentWindow, MsColors.black );
  327. VWindows.SetMonoAttr( VWindows.CurrentWindow, MsColors.plain );
  328. VWindows.ClearPart( VWindows.CurrentWindow, 1, 1,
  329. VWindows.EndCol(VWindows.CurrentWindow),
  330. VWindows.EndRow(VWindows.CurrentWindow) );
  331. VWindows.SetCursorHeight( VWindows.CurrentWindow, SavedCursorHeight );
  332. END RestoreDisplay;
  333. PROCEDURE CloseFiles();
  334. BEGIN
  335. DspFiles.CloseDisplayFile( ScreenFile );
  336. IF ModBase3.Initialized(DataFile) AND ModBase3.OpenDBF(DataFile) THEN
  337. ModBase3.CloseDBF( DataFile );
  338. DBIndxes.CloseIndex( IndexByName );
  339. END;
  340. END CloseFiles;
  341. VAR
  342. NextFrame : ScrnTypes.FrameKey;
  343. CurrentRecName: ARRAY [0..29] OF CHAR;
  344. CurrentRecNum: LONGINT;
  345. AsciiFileName, DbFileName: ARRAY [0..63] OF CHAR;
  346. dumbool: BOOLEAN;
  347. BEGIN (* MAIN *)
  348. ModBase3.NilDBF(DataFile);
  349. SavedCursorHeight := WindowPrims.GetCursorHeight();
  350. (*VWindows.GetCursorHeight( VWindows.CurrentWindow );*)
  351. SmartScreen.SetCursorHeight(0);
  352. (* VWindows.SetCursorHeight( VWindows.CurrentWindow, 0 );*)
  353. ErrorManager.AddTermProc( RestoreDisplay );
  354. ErrorManager.AddTermProc( CloseFiles );
  355. CurrentRecName := '';
  356. CurrentRecNum := VAL( LONGINT, 1 );
  357. ScreenDisplay.OpenDisplayFile( ScreenFile, 'AddrBook.DSP' );
  358. ScreenDisplay.Display( 1 );
  359. (* the box and the banner *)
  360. NextFrame := 8;
  361. ScreenInput.Input( NextFrame );
  362. (* Prompts for the name of the database file; you could get
  363. it from the command line if you wanted to. *)
  364. ScreenInput.ReadInput( DspFiles.MainFrame, DbFileName,
  365. dumbool, 'filename' );
  366. StrEdit.CrunchBlanks( DbFileName );
  367. IF GetNewDbFile( DataFile, IndexByName, DbFileName ) THEN
  368. LOOP
  369. (*NextFrame should always be 2 at this point.*)
  370. ScreenInput.Input( NextFrame );
  371. CASE NextFrame OF
  372. 11: (*User has selected Record option.*)
  373. ScreenInput.Input( NextFrame );
  374. (* This is the drop-down menu. *)
  375. IF NextFrame # StrConv.ReturnedInt(DspFiles.MainFrame^.parent) THEN
  376. CASE NextFrame OF
  377. 5: (* user wants a Specific record *)
  378. ScreenInput.Input( NextFrame );
  379. (* Prompts for the name of the record. *)
  380. IF NextFrame = UserOps.EndCode THEN
  381. (*User wants to exit program.*)
  382. EXIT;
  383. ELSE
  384. ScreenInput.ReadInput( DspFiles.MainFrame,
  385. CurrentRecName, dumbool, 'name' );
  386. NextFrame := ProcessNamedRecord( CurrentRecName,
  387. CurrentRecNum );
  388. (*NextFrame should always be 2 at this point.*)
  389. END;
  390. | 1000: (* user wants Next record *)
  391. IF (CurrentRecNum <= ModBase3.NumberRecords(DataFile)) THEN
  392. INC( CurrentRecNum );
  393. NextFrame := ProcessNumberedRecord(
  394. CurrentRecNum, FALSE, '' );
  395. ELSE
  396. NextFrame := 2;
  397. END;
  398. | 1001: (* user wants Prev record *)
  399. IF (CurrentRecNum > VAL(LONGINT, 1)) THEN
  400. DEC( CurrentRecNum );
  401. NextFrame := ProcessNumberedRecord(
  402. CurrentRecNum, FALSE, '' );
  403. ELSE
  404. NextFrame := 2;
  405. END;
  406. END;
  407. END;
  408. | 8: (*User has selected File option.*)
  409. CurrentRecName := '';
  410. CurrentRecNum := VAL( LONGINT, 1 );
  411. REPEAT
  412. ScreenInput.Input( NextFrame );
  413. (* Prompts for the name of the database file. *)
  414. ScreenInput.ReadInput( DspFiles.MainFrame,
  415. DbFileName, dumbool, 'filename' );
  416. StrEdit.CrunchBlanks( DbFileName );
  417. IF NOT GetNewDbFile( DataFile, IndexByName, DbFileName ) THEN
  418. EXIT;
  419. END;
  420. UNTIL ModBase3.OpenDBF(DataFile);
  421. | 6: (*User has selected Import option.*)
  422. ScreenInput.Input( NextFrame );
  423. ScreenInput.ReadInput( DspFiles.MainFrame,
  424. AsciiFileName, dumbool, 'filename' );
  425. IF NOT ImportFromAscii( DataFile, IndexByName,
  426. AsciiFileName ) THEN
  427. IF NOT Confirm( 'Error importing file. Continue?' ) THEN
  428. EXIT;
  429. END;
  430. END;
  431. NextFrame := 2;
  432. | 7: (*User has selected Export option.*)
  433. ScreenInput.Input( NextFrame );
  434. ScreenInput.ReadInput( DspFiles.MainFrame,
  435. AsciiFileName, dumbool, 'filename' );
  436. ExportToAscii( DataFile, AsciiFileName );
  437. NextFrame := 2;
  438. | UserOps.EndCode: EXIT;
  439. ELSE
  440. IF NOT Confirm(
  441. 'Unanticipated value returned from frame 2. Continue?') THEN
  442. EXIT;
  443. END;
  444. END;
  445. END;
  446. END;
  447. END AddrBook.
  448.