ADDRESS.MOD 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. MODULE Address;
  2. (*
  3. Copyright 1989 by Jensen & Partners International, All Rights Reserved
  4. *)
  5. IMPORT IO, FIO, Window, Btree, Str, Lib, Misc;
  6. TYPE
  7. AddrKey = ARRAY[0..25] OF CHAR;
  8. AddrRec = RECORD
  9. LName : ARRAY[0..14] OF CHAR;
  10. FName : ARRAY[0..9] OF CHAR;
  11. Street : ARRAY[0..25] OF CHAR;
  12. City : ARRAY[0..15] OF CHAR;
  13. State : ARRAY[0..1] OF CHAR;
  14. Zip : ARRAY[0..4] OF CHAR;
  15. Phone : ARRAY[0..12] OF CHAR;
  16. END; (* record *)
  17. CharSet = SET OF CHAR;
  18. VAR
  19. choice, ch2 : CHAR;
  20. FOUND,
  21. DONE : BOOLEAN;
  22. DataColor,
  23. TemplateColor : Window.Color;
  24. NameFile : Btree.FHandle; (* physical file handle *)
  25. NameData, (* logical data file handle *)
  26. NameIndex : Btree.IHandle; (* logical index file handle *)
  27. blankAddr,
  28. tempAddr : AddrRec;
  29. Create : BOOLEAN;
  30. PROCEDURE MAKEKEY(keyA,myRecA: ADDRESS);
  31. VAR
  32. key : POINTER TO AddrKey;
  33. myRec : POINTER TO AddrRec;
  34. i,j : CARDINAL;
  35. BEGIN
  36. key := keyA;
  37. myRec := myRecA;
  38. Str.Copy(key^,myRec^.LName);
  39. i := Str.Length(key^);
  40. WHILE (i#0) AND (key^[i-1]=' ') DO
  41. key^[i-1] := 0C;
  42. DEC(i);
  43. END; (* while *)
  44. Str.Append(key^," ");
  45. Str.Append(key^,myRec^.FName);
  46. i := Str.Length(key^);
  47. WHILE (i#0) AND (key^[i-1]=' ') DO
  48. key^[i-1] := 0C;
  49. DEC(i);
  50. END; (* while *)
  51. Str.Caps(key^);
  52. END MAKEKEY;
  53. PROCEDURE COMPARE(key1,key2: ADDRESS): Btree.CmpRes;
  54. (* compare two keys, and determine which is "smaller" *)
  55. BEGIN
  56. RETURN Btree.CmpRes(Str.Compare(AddrKey(key1^),AddrKey(key2^))+1);
  57. END COMPARE;
  58. PROCEDURE Beep();
  59. BEGIN
  60. Lib.Speaker(1500,10);
  61. END Beep;
  62. PROCEDURE WriteAt(row,col: CARDINAL; txt: ARRAY OF CHAR);
  63. BEGIN
  64. Window.GotoXY(col,row);
  65. IO.WrStr(txt);
  66. END WriteAt;
  67. PROCEDURE Template();
  68. BEGIN
  69. Window.TextColor(TemplateColor);
  70. WriteAt(3,3,"Name:");
  71. WriteAt(3,50,"(first last)");
  72. WriteAt(4,3,"Address:");
  73. WriteAt(5,3,"City:");
  74. WriteAt(5,40,"State:");
  75. WriteAt(5,55,"Zip:");
  76. WriteAt(6,3,"Phone:");
  77. END Template;
  78. PROCEDURE Display(myRec: AddrRec);
  79. BEGIN
  80. Window.TextColor(DataColor);
  81. WriteAt(3,12,myRec.FName); IO.WrStr(" "); IO.WrStr(myRec.LName);
  82. WriteAt(4,12,myRec.Street);
  83. WriteAt(5,12,myRec.City);
  84. WriteAt(5,47,myRec.State);
  85. WriteAt(5,60,myRec.Zip);
  86. WriteAt(6,12,myRec.Phone);
  87. END Display;
  88. PROCEDURE GetMenu(Prompt: ARRAY OF CHAR; OKChars: CharSet;
  89. VAR ch: CHAR);
  90. VAR
  91. OK : BOOLEAN;
  92. MenuWin : Window.WinType;
  93. i : CARDINAL;
  94. BEGIN
  95. MenuWin := Window.Open( Window.WinDef( 0, 22, 79, 24,
  96. Window.White,Window.Black,TRUE,FALSE,TRUE,TRUE,
  97. Window.SingleFrame,Window.White,Window.Black) );
  98. i := Str.Length(Prompt);
  99. Window.Change(MenuWin,((80-i) DIV 2) -2,22, ((80-i) DIV 2) + i + 3, 24);
  100. Window.SetFrame(MenuWin,Window.SingleFrame,TemplateColor,Window.Black);
  101. Window.TextColor(DataColor);
  102. Window.Use(MenuWin);
  103. Window.PutOnTop(MenuWin);
  104. IO.WrStr(" ");
  105. IO.WrStr(Prompt);
  106. OK := FALSE;
  107. REPEAT
  108. ch := CAP(IO.RdKey());
  109. IF ch IN OKChars THEN
  110. OK := TRUE;
  111. ELSE
  112. Beep();
  113. END;
  114. UNTIL OK;
  115. Window.Close(MenuWin);
  116. END GetMenu;
  117. PROCEDURE ShowNames();
  118. VAR
  119. myRec : AddrRec;
  120. ch : CHAR;
  121. row : CARDINAL;
  122. switchColor : BOOLEAN;
  123. BEGIN
  124. Window.Clear();
  125. Btree.Reset(NameData);
  126. row := 1;
  127. switchColor := TRUE;
  128. WHILE Btree.Next(NameIndex,myRec) DO
  129. IF switchColor THEN
  130. Window.TextColor(TemplateColor);
  131. ELSE
  132. Window.TextColor(DataColor);
  133. END;
  134. switchColor := NOT switchColor;
  135. IO.WrStrAdj(myRec.LName, -17);
  136. IO.WrStrAdj(myRec.FName, -12);
  137. IO.WrStrAdj(myRec.Phone, -15);
  138. IO.WrLn();
  139. INC(row);
  140. IF row>23 THEN
  141. IO.WrLn();
  142. IO.WrStr("Press <ESC> to quit, any other key to continue: ");
  143. ch := IO.RdKey();
  144. IF ch = 33C THEN RETURN; END;
  145. Window.Clear();
  146. row := 1;
  147. END; (* if *)
  148. END; (* while *)
  149. END ShowNames;
  150. PROCEDURE FindName();
  151. VAR
  152. fname : AddrKey;
  153. myRec : AddrRec;
  154. ch : CHAR;
  155. BEGIN
  156. Window.Clear();
  157. Window.TextColor(TemplateColor);
  158. FOUND := FALSE;
  159. WriteAt(3,3,"Enter name as 'Last First' (e.g. 'Smith John').");
  160. WriteAt(4,3,"Be sure to include the space between the names.");
  161. WriteAt(5,3,"> ");
  162. Window.TextColor(DataColor);
  163. fname := '';
  164. Misc.InputStr(fname,25);
  165. Str.Caps(fname);
  166. Window.TextColor(TemplateColor);
  167. WriteAt(7,3,"Searching... ");
  168. IF Btree.Find(NameIndex,fname,myRec) THEN
  169. Window.Clear();
  170. Template();
  171. Display(myRec);
  172. FOUND := TRUE;
  173. ELSE
  174. WriteAt(7,20,"done. Failed exact search. Trying closest match.");
  175. Window.TextColor(DataColor);
  176. WriteAt(9,3,"Searching... ");
  177. IF Btree.Search(NameIndex,fname,myRec) THEN
  178. Window.Clear();
  179. Template();
  180. Display(myRec);
  181. FOUND := TRUE;
  182. REPEAT
  183. GetMenu("N)ext, P)revious, or T)his one? ",
  184. CharSet{'N','P','T'},ch);
  185. WriteAt(10,3," ");
  186. CASE ch OF
  187. 'N' : IF Btree.Next(NameIndex,myRec) THEN
  188. Display(blankAddr);
  189. Display(myRec);
  190. ELSE
  191. WriteAt(10,3,"No more records found");
  192. Beep();
  193. Btree.Reset(NameIndex);
  194. Display(blankAddr);
  195. IF Btree.Prev(NameIndex,myRec) THEN
  196. Display(myRec);
  197. ELSE
  198. FOUND := FALSE;
  199. END;
  200. END;
  201. | 'P' : IF Btree.Prev(NameIndex,myRec) THEN
  202. Display(blankAddr);
  203. Display(myRec);
  204. ELSE
  205. WriteAt(10,3,"No more records found");
  206. Beep();
  207. Btree.Reset(NameIndex);
  208. Display(blankAddr);
  209. IF Btree.Next(NameIndex,myRec) THEN
  210. Display(myRec);
  211. ELSE
  212. FOUND := FALSE;
  213. END;
  214. END;
  215. ELSE
  216. Beep();
  217. END; (* case *)
  218. UNTIL ch = 'T';
  219. ELSE
  220. WriteAt(9,20,"done. Failed closest match search.");
  221. END; (* if *)
  222. END; (* if *)
  223. END FindName;
  224. PROCEDURE AddName();
  225. VAR
  226. myRec : AddrRec;
  227. ch : CHAR;
  228. BEGIN
  229. Window.Clear();
  230. Template();
  231. ch := 'N';
  232. myRec := blankAddr;
  233. REPEAT
  234. Window.TextColor(DataColor);
  235. Window.GotoXY(12,3); Misc.InputStr(myRec.FName,10);
  236. Window.GotoXY(35,3); Misc.InputStr(myRec.LName,15);
  237. Window.GotoXY(12,4); Misc.InputStr(myRec.Street,25);
  238. Window.GotoXY(12,5); Misc.InputStr(myRec.City,15);
  239. Window.GotoXY(47,5); Misc.InputStr(myRec.State,2);
  240. Window.GotoXY(60,5); Misc.InputStr(myRec.Zip,5);
  241. Window.GotoXY(12,6); Misc.InputStr(myRec.Phone,12);
  242. GetMenu("Do these look ok? (Y/N) ",CharSet{'Y','N'},ch);
  243. UNTIL ch = 'Y';
  244. (* Now put it in the file *)
  245. Btree.Add(NameData,myRec,SIZE(myRec));
  246. END AddName;
  247. PROCEDURE DeleteName();
  248. VAR
  249. ch : CHAR;
  250. BEGIN
  251. FindName();
  252. IF FOUND THEN
  253. GetMenu("Delete this one? (Y/N) ",CharSet{'Y','N'},ch);
  254. IF ch = 'Y' THEN
  255. Btree.Delete(NameData);
  256. END; (* if *)
  257. END; (* if *)
  258. FOUND := FALSE;
  259. END DeleteName;
  260. BEGIN (* main program *)
  261. TemplateColor := Window.LightGreen;
  262. DataColor := Window.Yellow;
  263. Str.Copy(blankAddr.LName," ");
  264. Str.Copy(blankAddr.FName," ");
  265. Str.Copy(blankAddr.Street," ");
  266. Str.Copy(blankAddr.City," ");
  267. Str.Copy(blankAddr.State," ");
  268. Str.Copy(blankAddr.Zip," ");
  269. Str.Copy(blankAddr.Phone," ");
  270. Window.Clear();
  271. Create := NOT FIO.Exists("Addressb.ook");
  272. NameFile := Btree.Open("Addressb.ook",2,Btree.FixSize,FALSE,FALSE,Create);
  273. NameData := Btree.OpenData(NameFile,1,SIZE(AddrRec),Create);
  274. NameIndex := Btree.OpenIndex(NameFile,NameData,2,COMPARE,MAKEKEY,
  275. SIZE(AddrKey),TRUE,Create);
  276. DONE := FALSE;
  277. choice := ' ';
  278. REPEAT
  279. GetMenu("S)howNames F)indSomeone A)ddSomeone D)eleteSomeone Q)uit :",
  280. CharSet{'S','F','A','D','Q'},choice);
  281. CASE choice OF
  282. 'S' : ShowNames();
  283. | 'F' : FindName();
  284. | 'A' : AddName();
  285. | 'D' : DeleteName();
  286. | 'Q' : DONE := TRUE;
  287. ELSE
  288. Beep();
  289. END; (* case *)
  290. UNTIL DONE;
  291. Btree.Close(NameFile);
  292. END Address.
  293.