DBSCREEN.MOD 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. IMPLEMENTATION MODULE DBScreen;
  2. (*
  3. * ModBase
  4. * Release 3.0
  5. * By Don Fletcher & John McMonagle
  6. * (c) Copyright 1986 - 1991 PMI
  7. * P.O. Box 8402
  8. * Green Bay Wi 53308
  9. * All Rights Reserved
  10. *
  11. *)
  12. IMPORT SYSTEM;
  13. (*Repertoire modules*)
  14. IMPORT BigSets;
  15. IMPORT LowLevel;
  16. IMPORT KbdInput;
  17. IMPORT SmartScreen;
  18. IMPORT StrEdit;
  19. IMPORT StrInput;
  20. IMPORT StrConv;
  21. IMPORT M2Strings;
  22. IMPORT VWindows;
  23. IMPORT WindowPrims;
  24. IMPORT ModBase3;
  25. IMPORT ErrorManager;
  26. FROM MiscFunctions IMPORT FieldName, FieldNameChar,
  27. Alph, Trim, Upper;
  28. CONST Blank = ' ';
  29. MaxGets = 80;
  30. MaxField = 128;
  31. MaxLength = 256;
  32. MaxNLength = 18;
  33. CRnum = 13;
  34. TABnum = 9;
  35. BSPnum = 8;
  36. ESCnum = 27;
  37. BTBnum = 15 + KbdInput.Extended;
  38. (*back tab numeric code for extended scan code*)
  39. LARWnum = 75 + KbdInput.Extended;
  40. (*left arrow numeric code*)
  41. RARWnum = 77 + KbdInput.Extended;
  42. (*right arrow*)
  43. UARWnum = 72 + KbdInput.Extended;
  44. (*up arrow*)
  45. DARWnum = 80 + KbdInput.Extended;
  46. TYPE
  47. String = ARRAY [0..MaxField] OF CHAR;
  48. StrPtr = POINTER TO String;
  49. GetType = RECORD
  50. row: CARDINAL;
  51. col: CARDINAL;
  52. len: CARDINAL;
  53. val: StrPtr;
  54. END;
  55. InputArray = ARRAY [1..MaxGets] OF GetType;
  56. VAR input: InputArray;
  57. lastget: CARDINAL;
  58. PROCEDURE ValidType(ch: CHAR): BOOLEAN;
  59. BEGIN
  60. RETURN (CAP(ch)='C') OR (CAP(ch)='N') OR (CAP(ch)='L') OR
  61. (CAP(ch)='D') OR (CAP(ch)='M');
  62. END ValidType;
  63. PROCEDURE ValidSize(size: CARDINAL; fieldtype: CHAR): BOOLEAN;
  64. (* Checks to see whether size is valid for the given fieldtype*)
  65. BEGIN
  66. CASE CAP(fieldtype) OF
  67. 'C': RETURN (size >= 1) AND (size <= MaxLength);
  68. | 'N': RETURN (size >= 1) AND (size <= MaxNLength);
  69. | 'L': RETURN (size = 1);
  70. | 'D': RETURN (size = 8);
  71. | 'M': RETURN (size = 10);
  72. END;
  73. RETURN FALSE;
  74. END ValidSize;
  75. PROCEDURE ValidDec(size, decimalplaces: CARDINAL): BOOLEAN;
  76. BEGIN
  77. RETURN (decimalplaces <= size);
  78. END ValidDec;
  79. PROCEDURE GetDescriptors(VAR fields: ARRAY OF ModBase3.DBFieldDescriptor);
  80. VAR
  81. i, j, crow, ccol, lastfield, pagebottom, pagetop: CARDINAL;
  82. sizestring: ARRAY [0..2] OF CHAR;
  83. decstr: ARRAY [0..1] OF CHAR;
  84. confirmed: CHAR;
  85. ok: BOOLEAN;
  86. PROCEDURE UniqueName(testname: ARRAY OF CHAR): BOOLEAN;
  87. VAR i, matches: CARDINAL;
  88. BEGIN
  89. i := 0;
  90. matches := 0;
  91. WHILE (i <= lastfield) DO
  92. IF (M2Strings.CompareStr(fields[i].name, testname) = 0) THEN
  93. INC(matches)
  94. END;
  95. INC(i)
  96. END;
  97. RETURN matches = 1;
  98. END UniqueName;
  99. BEGIN
  100. WindowPrims.PushColors();
  101. SmartScreen.ClearScreen();
  102. i := 0;
  103. pagetop := i;
  104. pagebottom := i+29;
  105. confirmed := 'N';
  106. Say(2, 5, 'NAME------ TYPE SIZE DEC');
  107. SmartScreen.SetAttribOrColor( SmartScreen.red,
  108. SmartScreen.blue, SmartScreen.ReverseVideo );
  109. REPEAT
  110. crow := (i MOD 15) + 4;
  111. ccol := 5+((i DIV 15) * 35);
  112. Say(crow, ccol, fields[i].name);
  113. Say(crow, ccol+12, fields[i].fldtype);
  114. StrConv.CardinalToStr(fields[i].size, 3, sizestring);
  115. Say(crow, ccol+18, sizestring);
  116. StrConv.CardinalToStr(fields[i].decplaces, 3, decstr);
  117. Say(crow, ccol+24, decstr);
  118. INC(i);
  119. UNTIL (NOT FieldName(fields[i].name)) OR (i >= pagebottom);
  120. lastfield := i-1;
  121. REPEAT
  122. i := 0;
  123. REPEAT
  124. REPEAT
  125. crow := (i MOD 15) + 4;
  126. ccol := 5+((i DIV 15) * 35);
  127. Get(crow, ccol, fields[i].name);
  128. Get(crow, ccol + 12, fields[i].fldtype);
  129. ReadGets;
  130. fields[i].fldtype := CAP(fields[i].fldtype);
  131. Upper(fields[i].name);
  132. Say(crow, ccol, fields[i].name);
  133. Say(crow, ccol + 12, fields[i].fldtype);
  134. UNTIL (FieldName(fields[i].name) AND UniqueName(fields[i].name))
  135. AND (ValidType(fields[i].fldtype))
  136. OR (fields[i].name[0] = ' ')
  137. OR (lastdirection = Escape);
  138. IF ((fields[i].name[0]) # ' ') AND (lastdirection # Back) THEN
  139. CASE fields[i].fldtype OF
  140. 'D' : fields[i].size := 8 |
  141. 'M' : fields[i].size := 10 |
  142. 'L' : fields[i].size := 1
  143. ELSE
  144. StrConv.CardinalToStr(fields[i].size, 3, sizestring);
  145. StrConv.CardinalToStr(fields[i].decplaces, 3, decstr);
  146. REPEAT
  147. Get(crow, ccol + 18, sizestring);
  148. ReadGets;
  149. Trim(sizestring);
  150. ok := StrConv.StrToCardinal(sizestring, 0, fields[i].size);
  151. UNTIL ok AND ValidSize(fields[i].size, fields[i].fldtype);
  152. IF fields[i].fldtype = 'N' THEN
  153. REPEAT
  154. Get(crow, ccol + 24, decstr);
  155. ReadGets;
  156. Trim(decstr);
  157. ok := StrConv.StrToCardinal(decstr, 0, fields[i].decplaces);
  158. UNTIL ok AND ValidDec(fields[i].size, fields[i].decplaces);
  159. END;
  160. END; (* case *)
  161. END;
  162. IF (i < lastfield) AND (fields[i].name[0] = ' ') THEN
  163. (* the user has deleted a field in mid-record so the subsequent
  164. fields must be 'sucked up' *)
  165. FOR j := i TO lastfield DO
  166. fields[j] := fields[j+1]
  167. END (* for *);
  168. END;
  169. IF lastdirection = Ahead THEN
  170. IF i < MaxField-1 THEN
  171. IF i >= lastfield THEN INC(lastfield) END;
  172. INC(i)
  173. END;
  174. ELSIF lastdirection = Back THEN
  175. IF i > 0 THEN
  176. DEC(i)
  177. END;
  178. END;
  179. UNTIL (lastdirection = Escape)
  180. OR (fields[i-1].name[0] = ' ')
  181. OR (i < pagetop)
  182. OR (i > pagebottom);
  183. (* CONFIRM *)
  184. Say(24,5, 'Enter "Y" to confirm - ');
  185. Get(24, 28, confirmed);
  186. ReadGets;
  187. UNTIL CAP(confirmed) = 'Y';
  188. WindowPrims.PopColors();
  189. END GetDescriptors;
  190. PROCEDURE ModifyDBStruc(VAR alias: ModBase3.DBFile);
  191. VAR displayoffset: CARDINAL;
  192. new: ModBase3.DBFile;
  193. BEGIN
  194. (* new = alias;
  195. ChangeExt(alias.name, 'BAK');
  196. (* Rename alias to *.bak *)
  197. Rename(alias.fileID, alias.name);
  198. CloseDBF(alias);
  199. (* Rename alias to *.bak *)
  200. GetDescriptors(new.fieldlist);
  201. BuildDBF(new.name, new.fieldlist, alias);
  202. CloseDBF(alias);
  203. (* UpDate from *.bak *)
  204. *)
  205. END ModifyDBStruc;
  206. (*
  207. PROCEDURE ChangeExt(VAR filename: ARRAY OF CHAR; ext: ARRAY OF CHAR);
  208. (* add the ext after the last period in the filename *)
  209. VAR i, j: CARDINAL;
  210. BEGIN
  211. i := M2Strings.Length(filename)-1;
  212. WHILE (i > 0) AND (filename[i] # '.') DO
  213. DEC(i)
  214. END;
  215. IF i = 0 THEN
  216. i := M2Strings.Length(filename)-1;
  217. END;
  218. FOR j := i+1 TO i+M2Strings.Length(ext)+1 DO
  219. filename[j] := ext[j-(i+1)]
  220. END;
  221. IF HIGH(filename) > (i+M2Strings.Length(ext)+1) THEN
  222. filename[i+M2Strings.Length(ext)] := 0C;
  223. END;
  224. END ChangeExt;
  225. *)
  226. PROCEDURE CreateDBF(dbfilename: ARRAY OF CHAR; VAR alias: ModBase3.DBFile);
  227. VAR descarray: ARRAY [0..MaxField-1] OF ModBase3.DBFieldDescriptor;
  228. i: CARDINAL;
  229. BEGIN
  230. (* initialize field descriptor array *)
  231. FOR i := 0 TO MaxField-1 DO
  232. WITH descarray[i] DO
  233. name := ' ';
  234. size := 0;
  235. fldtype := ' ';
  236. decplaces := 0;
  237. offset := 0;
  238. END;
  239. END;
  240. GetDescriptors(descarray);
  241. IF ModBase3.BuildDBF(descarray,MaxField, alias) # 0 THEN
  242. ErrorManager.WARN('Unable to create DataBase File')
  243. END;
  244. END CreateDBF;
  245. PROCEDURE Row(): CARDINAL;
  246. VAR row, col: CARDINAL;
  247. BEGIN
  248. WindowPrims.GetCursorCoords( col, row );
  249. RETURN row;
  250. END Row;
  251. PROCEDURE Col(): CARDINAL;
  252. VAR row, col: CARDINAL;
  253. BEGIN
  254. WindowPrims.GetCursorCoords( col, row );
  255. RETURN col;
  256. END Col;
  257. PROCEDURE Say(row, col: CARDINAL; s: ARRAY OF CHAR);
  258. BEGIN
  259. WindowPrims.PushColors();
  260. (* Note that we don't push and pop the cursor size or
  261. position here or in Get, and we don't turn it off,
  262. because we don't want it to flash between fields as they
  263. are initially written. Means you ought to turn it off
  264. before doing a series of Say and Get statements. *)
  265. SmartScreen.SetAttribOrColor( writeattr.fore, writeattr.back,
  266. writeattr.MonoAttr );
  267. SmartScreen.WriteAt( col, row, s );
  268. SmartScreen.GotoXY( SmartScreen.NominalCol,
  269. SmartScreen.NominalRow );
  270. (* The GotoXY guarantees consistent cursor placement between
  271. VideoMethods; in DMA mode, WriteAt doesn't move the
  272. cursor. See documentation for SmartScreen in the
  273. Repertoire manual. *)
  274. WindowPrims.PopColors();
  275. END Say;
  276. PROCEDURE Get(row, col: CARDINAL; VAR s: ARRAY OF CHAR);
  277. BEGIN
  278. WindowPrims.PushColors();
  279. (* pad the string with trailing blanks *)
  280. WHILE M2Strings.Length(s) <= HIGH(s) DO
  281. StrEdit.Append( s, Blank );
  282. END;
  283. INC(lastget);
  284. input[lastget].row := row;
  285. input[lastget].col := col;
  286. input[lastget].len := HIGH(s)+1;
  287. input[lastget].val := SYSTEM.ADR(s);
  288. SmartScreen.SetAttribOrColor( readattr.fore, readattr.back,
  289. readattr.MonoAttr );
  290. SmartScreen.GotoXY( col, row );
  291. SmartScreen.WriteAt( col, row, s );
  292. SmartScreen.GotoXY( SmartScreen.NominalCol,
  293. SmartScreen.NominalRow );
  294. WindowPrims.PopColors();
  295. END Get;
  296. PROCEDURE ReadGets;
  297. VAR
  298. tmpLen, currentget, CursorPos, LastKey : CARDINAL;
  299. ExitKeys: KbdInput.KeyNumSet;
  300. InsertMode: BOOLEAN;
  301. TmpStr: ARRAY [0..128] OF CHAR;
  302. tmpStrPtr: StrPtr;
  303. LocalInput: InputArray;
  304. BEGIN
  305. LocalInput := input;
  306. (* We do this to make the routine easier to follow in the
  307. runtime debugger. The global input variable isn't
  308. normally visible there because it's global to a module
  309. outside the calling chain. *)
  310. WindowPrims.PushColors();
  311. WindowPrims.PushCursorCoords();
  312. (* Insulates calling procedures from the color choices and
  313. cursor-position changes we make here. We don't need to
  314. push and pop the cursor size or turn it off because
  315. ReadWithEdits handles that internally. *)
  316. SmartScreen.SetAttribOrColor( readattr.fore, readattr.back,
  317. readattr.MonoAttr );
  318. InsertMode := TRUE;
  319. BigSets.InitSet( ExitKeys );
  320. BigSets.AppendSet( ExitKeys, '{8, 9, 13, 27, 271, 328, 329, 336, 337}' );
  321. (* Means BackSpace, TAB, BackTab, CR, ESC, and the arrow
  322. keys let you out of a field. *)
  323. IF lastget > 0 THEN
  324. currentget:= 1;
  325. lastdirection := Nowhere;
  326. WHILE (lastdirection # Escape) AND
  327. (currentget > 0) AND
  328. (currentget <= lastget) DO
  329. CursorPos := 0;
  330. tmpStrPtr := LocalInput[currentget].val;
  331. (* Break out the steps because otherwise Stony Brook
  332. generates code that causes a protection fault
  333. when the pointer is dereferenced. *)
  334. tmpLen := LocalInput[currentget].len;
  335. LowLevel.Move(tmpStrPtr, SYSTEM.ADR(TmpStr), tmpLen);
  336. (* We have to do this to prevent overflows; since val
  337. points to an area of memory larger than what we are
  338. really considering the variable here, ReadWithEdits
  339. can't reliably tell whether it should put a length
  340. byte at the end of the string. Notice that we can't
  341. use M2Strings.Copy because it will begin by trying to
  342. make a copy of all HIGH+1 bytes of the first argument
  343. on the stack. In this case, they aren't all there.*)
  344. StrInput.ReadWithEdits( VWindows.CurrentWindow, TmpStr,
  345. LocalInput[currentget].col, LocalInput[currentget].row,
  346. LocalInput[currentget].len, CursorPos, InsertMode, FALSE,
  347. LastKey, KbdInput.AnyKeyNum, ExitKeys );
  348. LowLevel.Move( SYSTEM.ADR(TmpStr), LocalInput[currentget].val,
  349. LocalInput[currentget].len );
  350. CASE LastKey OF
  351. BSPnum, BTBnum, LARWnum, UARWnum:
  352. DEC( currentget );
  353. lastdirection := Back;
  354. | CRnum, TABnum, RARWnum, DARWnum:
  355. INC(currentget);
  356. lastdirection := Ahead;
  357. | ESCnum:
  358. lastdirection := Escape
  359. ELSE (* nothing *)
  360. END;
  361. END; (*WHILE*)
  362. FOR currentget := 1 TO lastget DO
  363. tmpStrPtr := LocalInput[currentget].val;
  364. tmpLen := LocalInput[currentget].len;
  365. LowLevel.Move(tmpStrPtr, SYSTEM.ADR(TmpStr), tmpLen);
  366. (* Same problem here; the procedure that strips the
  367. blanks can't reliably determine where the end of the
  368. string is because we are trying to pass it only a
  369. part of the string. So we copy into a local
  370. variable. *)
  371. StrEdit.CutTrailingChars( Blank, TmpStr );
  372. LowLevel.Move( SYSTEM.ADR(TmpStr), LocalInput[currentget].val,
  373. LocalInput[currentget].len );
  374. END;
  375. lastget := 0;
  376. END; (* if *)
  377. WindowPrims.PopCursorCoords();
  378. WindowPrims.PopColors();
  379. input := LocalInput;
  380. END ReadGets;
  381. BEGIN (* main *)
  382. WITH readattr DO
  383. MonoAttr := SmartScreen.ReverseVideo;
  384. fore := SmartScreen.blue;
  385. back := SmartScreen.lightgrey;
  386. END;
  387. WITH writeattr DO
  388. MonoAttr := SmartScreen.plain;
  389. fore := SmartScreen.lightgrey;
  390. back := SmartScreen.blue;
  391. END;
  392. lastget := 0;
  393. END DBScreen.