MAKEFRAM.MOD 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935
  1. IMPLEMENTATION MODULE MakeFrame;
  2. (*
  3. * REPERTOIRE
  4. * Release 1.6
  5. * By Charles Bradford and Cole Brecheen
  6. * (c) Copyright 1985-1992 PMI
  7. * Green Bay, Wisconsin
  8. * All rights reserved
  9. * (414) 468-6040
  10. *
  11. * $Header: D:/logfiles/mods/makefram.mov 1.8 17 Mar 1991 18:02:14 coleb $
  12. *
  13. * Modified March 9, 1990 - mbc. Change syntax to allow Real.x, where x
  14. * is the number of decimal places on input for the real.
  15. * March 24, 1990 - mbc. move realDecPlaces declaration.
  16. *)
  17. (*EntryDiag:
  18. IMPORT Diagnostics;
  19. :EntryDiag*)
  20. IMPORT ByteFiddler;
  21. IMPORT ErrorManager;
  22. IMPORT FieldTypes;
  23. IMPORT GenLists;
  24. IMPORT LowLevel;
  25. IMPORT M2Strings;
  26. IMPORT MsColors;
  27. IMPORT NdxTypes;
  28. IMPORT Numbers;
  29. IMPORT NumTypes;
  30. IMPORT Parser;
  31. IMPORT PosUtils;
  32. IMPORT ScrnTypes;
  33. IMPORT ScrnUtl1;
  34. IMPORT StrConv;
  35. IMPORT StrCnv1;
  36. IMPORT StrEdit;
  37. IMPORT SYSTEM;
  38. IMPORT VStorage;
  39. IMPORT VWindows;
  40. VAR
  41. Initialized: BOOLEAN;
  42. TYPE
  43. CStackP = POINTER TO CStack;
  44. CStack =
  45. RECORD
  46. Ccode: CHAR;
  47. forec, backc: MsColors.AColor;
  48. atrbc: MsColors.AMonoAttribute;
  49. prv, nxt: CStackP;
  50. END;
  51. CONST
  52. AfterLastElmt = 65535;
  53. BorderChar = ':';
  54. MaxScrWidth = 255;
  55. EOF = 32C;
  56. EOL = 15C;
  57. FormFeed = 14C;
  58. blank = ' ';
  59. null = '';
  60. NoFrame = '';
  61. RecType = 1;
  62. SectnEnd = "}";
  63. (* Error Strings *)
  64. BadCommand = 'unrecognized command';
  65. CoEqErr = 'Designate colors with "="';
  66. CoFormErr = 'Color statements must be of form: (number, number) attrib';
  67. CoNumErr = 'Colors must be valid name or number < 16:';
  68. CornerErr = 'Upper left corner is not above and left of the lower right';
  69. DataErr = 'data list is missing or format is invalid';
  70. EdErr = 'number of lines for the editor field is missing';
  71. FewErr = 'Fewer fields in command area than on screen';
  72. FMErr = 'FieldMark (#) error: redefinition invalid or field not closed';
  73. FieldFormErr = 'invalid field type or keyword';
  74. FrameNameErr = "Frame name incorrect or missing; must have ':' in col 0";
  75. FrameErr = 'Frame must start with either ==== or frame name';
  76. GroupErr = 'Choice fields must be inside groups';
  77. HelpErr = 'help list is missing or format is invalid';
  78. HelpFErr = 'frame name for help is missing';
  79. InsuffMem = 'Too little memory';
  80. MoreErr = 'More fields in command section than on screen';
  81. NeedBracket = 'Max and min acceptable values in brackets are missing';
  82. NeedColon = 'colon after position or heading key word is missing';
  83. NeedParen = 'Field subcommands must start with "("';
  84. NeedQuote = 'field name (may be null) in quotes must be supplied';
  85. NestErr = 'Improper nesting of color codes';
  86. NormalErr = 'normal next frame name is missing';
  87. NumSepErr = 'Either numbers or separators are invalid, check format';
  88. ParentErr = 'Bad Parent Frame';
  89. PlacementErr = 'Invalid designation of Frame Above, Below, Left, or Right';
  90. PromptErr = 'prompt text is missing';
  91. SectnEndErr = 'Command sections must end with "}"';
  92. SectnErr = 'Command sections must start with ":{"';
  93. SelectorErr = 'field selector must be a single character';
  94. WinFormErr = 'Invalid keyword in windows subsection command';
  95. VAR
  96. (* the following are screen characteristics that may be
  97. altered gloablly for a file by commands in any screen frame *)
  98. ColorKeys : ARRAY [0 .. 255] OF CHAR;
  99. (* defined colors *)
  100. KeyFors, KeyBacks : ARRAY [0 .. 255] OF MsColors.AColor;
  101. KeyAtrbs : ARRAY [0 .. 255] OF MsColors.AMonoAttribute;
  102. DefaultFore, DefaultBack, DefaultBordfor, DefaultBordbak,
  103. DefaultSelfor, DefaultSelbak, DefaultPbfor, DefaultPbbak,
  104. DefaultMsgfor, DefaultMsgbak, DefaultPromfor,
  105. DefaultPrombak: MsColors.AColor;
  106. DefaultAtrb, DefaultBordatrb, DefaultSelatrb, DefaultPbatrb,
  107. DefaultMsgatrb, DefaultPromatrb : MsColors.AMonoAttribute;
  108. ColorStack: CStackP;
  109. ColorBase: CStack;
  110. (* We make ColorBase a record instead of a pointer so as to
  111. avoid doing dynamic memory allocation during the module
  112. initialization sequence. *)
  113. FieldMark : CHAR;
  114. (* field delimiter in the screen image *)
  115. ReplacingFieldMarks : BOOLEAN;
  116. (* the following variables are used repeatedly and are global
  117. solely for convenience *)
  118. CurrentWord: ARRAY [0..MaxScrWidth] OF CHAR;
  119. (* usually the word retrieved by using GetNextWord *)
  120. Terminator: CHAR;
  121. (* usually the character terminating the word read with GetNextWord *)
  122. CurrentLine: CARDINAL;
  123. (* the line of the input genlist currently being processed *)
  124. CurrentIndex: CARDINAL;
  125. (* the index of the character on the current line currently
  126. being processed *)
  127. DataList, PromptList, HelpList, EdList, FieldList, ImageList, LinkedFrames:
  128. GenLists.GenList;
  129. ErrStrGlobal : ARRAY [0 .. 255] OF CHAR;
  130. FrameRec: ScrnTypes.PackedFrameRec;
  131. HelpFrame, ParentFrame, NormalNextFrame, FrameAbove, FrameBelow,
  132. FrameLeft, FrameRight: ScrnTypes.AFrameName;
  133. BadLineGlobal: CARDINAL;
  134. InListGlobal: GenLists.GenList;
  135. FieldCount, LineCount: CARDINAL;
  136. PROCEDURE EnclosureCount( Opener, Closer: ARRAY OF CHAR;
  137. VAR TheStr: ARRAY OF CHAR; VAR TheCount: INTEGER;
  138. VAR StartFound, EndFound: BOOLEAN; CutWhenFound: BOOLEAN );
  139. (* A general purpose procedure for keeping track of delimiters
  140. that can cross strings and that can be nested. It's meant
  141. to be called in a loop, and is useful in parsing series of
  142. strings when you need to find closing quotes, braces,
  143. brackets, etc. The first time you call it, StartFound and
  144. EndFound should be false, and TheCount should be 0. If at
  145. some point in the loop you pass it a string that contains
  146. Opener, it sets StartFound to TRUE and begins to count
  147. instances of Opener and Closer in TheStr--each Opener
  148. increments TheCount, and each Closer decrements it. Because
  149. StartFound will still be true the next time EnclosureCount
  150. is called, this continues until the Closer that matches
  151. Opener is found (i.e., until TheCount returns to 0). At
  152. that point, EndFound gets set to TRUE. If the CutWhenFound
  153. parameter is TRUE, the first Opener and the last Closer are
  154. deleted from TheStr. *)
  155. VAR
  156. StrIndex : INTEGER;
  157. StrLngth, OpenerLngth, CloserLngth : CARDINAL;
  158. BEGIN
  159. IF NOT StartFound THEN
  160. TheCount := 0;
  161. IF NOT PosUtils.Present( Opener, TheStr ) THEN
  162. RETURN;
  163. END;
  164. END;
  165. EndFound := FALSE;
  166. StrLngth := M2Strings.Length( TheStr );
  167. OpenerLngth := M2Strings.Length( Opener );
  168. CloserLngth := M2Strings.Length( Closer );
  169. StrIndex := 0;
  170. WHILE (StrIndex < INTEGER(StrLngth)) AND (NOT EndFound) DO
  171. IF ((OpenerLngth = 1) AND (TheStr[StrIndex] = Opener[0]))
  172. OR (PosUtils.PosAdr( Opener,
  173. LowLevel.AddAddr(SYSTEM.ADR(TheStr),StrIndex),
  174. OpenerLngth ) = 0) THEN
  175. TheCount := TheCount + 1;
  176. IF (TheCount = 1) THEN
  177. StartFound := TRUE;
  178. IF CutWhenFound THEN
  179. M2Strings.Delete( TheStr, StrIndex, M2Strings.Length(Opener) );
  180. IF StrIndex # 0 THEN
  181. DEC( StrIndex );
  182. END;
  183. END;
  184. END;
  185. END;
  186. IF ((CloserLngth = 1) AND (TheStr[StrIndex] = Closer[0]))
  187. OR (PosUtils.PosAdr( Closer,
  188. LowLevel.AddAddr(SYSTEM.ADR(TheStr),StrIndex),
  189. CloserLngth ) = 0) THEN
  190. TheCount := TheCount - 1;
  191. IF StartFound AND (TheCount = 0) THEN
  192. IF CutWhenFound THEN
  193. M2Strings.Delete( TheStr, StrIndex, M2Strings.Length(Closer) );
  194. END;
  195. EndFound := TRUE;
  196. END;
  197. END;
  198. INC( StrIndex );
  199. END;
  200. END EnclosureCount;
  201. PROCEDURE EncodeColor( colr: MsColors.AColor): CHAR;
  202. VAR
  203. tmpbyte:
  204. RECORD
  205. CASE : BOOLEAN OF
  206. TRUE: tcolr: MsColors.AColor;
  207. | FALSE: tlow, thi: CHAR;
  208. END;
  209. END;
  210. BEGIN
  211. tmpbyte.tcolr := colr;
  212. ScrnUtl1.EncodeByte( tmpbyte.tlow);
  213. RETURN tmpbyte.tlow;
  214. END EncodeColor;
  215. PROCEDURE EncodeAttrib( att: MsColors.AMonoAttribute): CHAR;
  216. VAR
  217. tmpbyte:
  218. RECORD
  219. CASE : BOOLEAN OF
  220. TRUE: tatt: MsColors.AMonoAttribute;
  221. | FALSE: tlow, thi: CHAR;
  222. END;
  223. END;
  224. BEGIN
  225. tmpbyte.tatt := att;
  226. ScrnUtl1.EncodeByte( tmpbyte.tlow);
  227. RETURN tmpbyte.tlow;
  228. END EncodeAttrib;
  229. PROCEDURE ReportErr( ErrDesc: ARRAY OF CHAR) : BOOLEAN;
  230. (* appends an error description to the current line of text
  231. and sets the bad line number. Always returns FALSE for
  232. calling convenience (see usage below). *)
  233. BEGIN
  234. M2Strings.Assign( Parser.TheLine, ErrStrGlobal);
  235. StrEdit.CutLeadingChars( ' ', ErrStrGlobal );
  236. StrEdit.CutTrailingChars( ' ', ErrStrGlobal );
  237. M2Strings.Insert( ' "', ErrStrGlobal, 0 );
  238. StrEdit.Append( ErrStrGlobal, '" : ');
  239. StrEdit.Append( ErrStrGlobal, ErrDesc);
  240. BadLineGlobal := CurrentLine;
  241. RETURN FALSE;
  242. END ReportErr;
  243. PROCEDURE GetColorNum( str: ARRAY OF CHAR; VAR num: CARDINAL ): BOOLEAN;
  244. BEGIN
  245. IF (StrConv.StrToCardinal( str, 0, num)) THEN
  246. IF (num > 15) THEN
  247. RETURN ReportErr( CoNumErr);
  248. END;
  249. RETURN TRUE;
  250. END;
  251. IF PosUtils.Equal('BLACK', str) THEN
  252. num := 0;
  253. ELSIF PosUtils.Equal('BLUE', str) THEN
  254. num := 1;
  255. ELSIF PosUtils.Equal('GREEN', str) THEN
  256. num := 2;
  257. ELSIF PosUtils.Equal('CYAN', str) THEN
  258. num := 3;
  259. ELSIF PosUtils.Equal('RED', str) THEN
  260. num := 4;
  261. ELSIF PosUtils.Equal('MAGENTA', str) THEN
  262. num := 5;
  263. ELSIF PosUtils.Equal('BROWN', str) THEN
  264. num := 6;
  265. ELSIF PosUtils.Equal('LIGHTGREY', str) THEN
  266. num := 7;
  267. ELSIF PosUtils.Equal('DARKGREY', str) THEN
  268. num := 8;
  269. ELSIF PosUtils.Equal('LIGHTBLUE', str) THEN
  270. num := 9;
  271. ELSIF PosUtils.Equal('LIGHTGREEN', str) THEN
  272. num := 10;
  273. ELSIF PosUtils.Equal('LIGHTCYAN', str) THEN
  274. num := 11;
  275. ELSIF PosUtils.Equal('PINK', str) THEN
  276. num := 12;
  277. ELSIF PosUtils.Equal('LIGHTMAGENTA', str) THEN
  278. num := 13;
  279. ELSIF PosUtils.Equal('YELLOW', str) THEN
  280. num := 14;
  281. ELSIF PosUtils.Equal('BRIGHTWHITE', str) THEN
  282. num := 15;
  283. ELSE
  284. num := 0;
  285. RETURN ReportErr( CoNumErr);
  286. END;
  287. RETURN TRUE;
  288. END GetColorNum;
  289. PROCEDURE NameToAttrib( TheName : ARRAY OF CHAR; VAR answer :
  290. MsColors.AMonoAttribute) : BOOLEAN;
  291. (* converts a string to a text attribute *)
  292. BEGIN
  293. IF PosUtils.Equal('PLAIN',TheName) THEN
  294. answer := MsColors.plain;
  295. ELSIF PosUtils.Equal('BOLD',TheName) THEN
  296. answer := MsColors.bold;
  297. ELSIF PosUtils.Equal('UNDERSCORED',TheName) THEN
  298. answer := MsColors.underscored;
  299. ELSIF PosUtils.Equal('BLINKING',TheName) THEN
  300. answer := MsColors.blinking;
  301. ELSIF PosUtils.Equal('REVERSEVIDEO',TheName) THEN
  302. answer := MsColors.ReverseVideo;
  303. ELSIF PosUtils.Equal('UNDERLINED',TheName) THEN
  304. answer := MsColors.underscored;
  305. ELSIF M2Strings.Length(TheName) = 0 THEN
  306. answer := MsColors.invisible;
  307. (* no attribute specified *)
  308. ELSE
  309. RETURN FALSE;
  310. END;
  311. RETURN TRUE;
  312. END NameToAttrib;
  313. PROCEDURE LastChar( VAR text: ARRAY OF CHAR): CHAR;
  314. (* cut blanks and return the last non-blnk character in the
  315. string *)
  316. BEGIN
  317. StrEdit.CutTrailingChars( blank, text);
  318. IF M2Strings.Length( text) > 0 THEN
  319. RETURN text[ M2Strings.Length( text) - 1];
  320. ELSE
  321. RETURN EOL;
  322. END;
  323. END LastChar;
  324. PROCEDURE CrunchToNextDelim( VAR StartingAndEndingAt: CARDINAL;
  325. VAR text: ARRAY OF CHAR );
  326. VAR
  327. last: CARDINAL;
  328. done: BOOLEAN;
  329. BEGIN
  330. last := M2Strings.Length(text);
  331. IF last = 0 THEN
  332. RETURN;
  333. ELSE
  334. DEC(last);
  335. END;
  336. done := FALSE;
  337. WHILE (StartingAndEndingAt <= last) AND (NOT done) DO
  338. IF text[StartingAndEndingAt] = ' ' THEN
  339. M2Strings.Delete( text, StartingAndEndingAt, 1 );
  340. ELSIF PosUtils.Present( text[StartingAndEndingAt],
  341. Parser.delimiters ) THEN
  342. done := TRUE;
  343. ELSE
  344. INC( StartingAndEndingAt );
  345. END;
  346. END;
  347. END CrunchToNextDelim;
  348. PROCEDURE NextWord( VAR word: ARRAY OF CHAR; VAR term: CHAR);
  349. (* uses global defaults to shorten call to GetNextWord for
  350. code readability and skiping comments*)
  351. BEGIN
  352. Parser.GetNextWord( InListGlobal, CurrentLine, CurrentIndex, word, term);
  353. WHILE PosUtils.Equal(word,Parser.StartComment) DO
  354. Parser.SkipComments(InListGlobal,CurrentIndex,CurrentLine);
  355. Parser.GetNextWord( InListGlobal, CurrentLine, CurrentIndex, word, term);
  356. END;
  357. END NextWord;
  358. PROCEDURE NextWordCap( VAR word: ARRAY OF CHAR; VAR term: CHAR);
  359. (* uses global defaults to shorten call to GetNextWord for
  360. code readability*)
  361. BEGIN
  362. NextWord( word, term);
  363. StrEdit.CAPstr( word);
  364. END NextWordCap;
  365. PROCEDURE NextCrunchedWord( VAR word: ARRAY OF CHAR; VAR term: CHAR);
  366. (* gets the next word with blanks deleted and not counted as a
  367. separator *)
  368. VAR
  369. line, index, spot, TypeCode, StrLngth: CARDINAL;
  370. BEGIN
  371. index:=CurrentIndex;
  372. line:=CurrentLine;
  373. IF CurrentLine <= GenLists.ListLength( InListGlobal ) THEN
  374. NextWord(word,term);
  375. IF line=CurrentLine THEN
  376. CurrentIndex:=index
  377. ELSE
  378. CurrentIndex:=0
  379. END;
  380. END;
  381. (* old version 7/17/91 John McMonagle
  382. WHILE (CurrentIndex >= M2Strings.Length( Parser.TheLine)) AND
  383. (CurrentLine < GenLists.ListLength( InListGlobal)) DO
  384. (* go to next line, skipping blank lines *)
  385. INC( CurrentLine);
  386. GenLists.GetElmt( InListGlobal, CurrentLine, Parser.TheLine, TypeCode);
  387. (*read next line*)
  388. CurrentIndex := 0;
  389. CrunchToNextDelim( CurrentIndex, Parser.TheLine );
  390. (*Set it back to 0.*)
  391. CurrentIndex := 0;
  392. Parser.SkipComments( InListGlobal, CurrentIndex, CurrentLine );
  393. (*We'll go back around if a comment was actually skipped.*)
  394. END;
  395. *)
  396. spot := CurrentIndex;
  397. CrunchToNextDelim( CurrentIndex, Parser.TheLine );
  398. CurrentIndex := spot;
  399. NextWord(word, term);
  400. StrEdit.CAPstr( word);
  401. END NextCrunchedWord;
  402. PROCEDURE GetNextSep( VAR Term: CHAR);
  403. (* A muddled function. Skips over blanks and leaves
  404. CurrentIndex sitting on the first non-blank character that
  405. follows. If that happens to be a delimiter, increments
  406. CurrentIndex once more. *)
  407. BEGIN
  408. WHILE (CurrentIndex < M2Strings.Length( Parser.TheLine)) AND
  409. (Parser.TheLine[ CurrentIndex] = blank) DO
  410. (* skip blanks *)
  411. INC( CurrentIndex);
  412. END;
  413. IF (CurrentIndex < M2Strings.Length( Parser.TheLine)) THEN
  414. (* return sep, if found *)
  415. Term := Parser.TheLine[ CurrentIndex];
  416. IF PosUtils.Present( Term, Parser.delimiters) THEN
  417. (* skip past separator found, so we start at
  418. beginning of next word next time *)
  419. INC( CurrentIndex);
  420. END;
  421. ELSE
  422. Term := EOL;
  423. (* if at end of line, return EOL *)
  424. END;
  425. END GetNextSep;
  426. PROCEDURE NextNum( VAR result: CARDINAL): BOOLEAN;
  427. (* converts next word into a CARDINAL. returns TRUE if OK *)
  428. VAR
  429. Word: ARRAY [0..MaxScrWidth] OF CHAR;
  430. BEGIN
  431. NextWord(Word,
  432. Terminator);
  433. RETURN StrConv.StrToCardinal( Word, 0, result);
  434. END NextNum;
  435. PROCEDURE FindCmdBegin( VAR line, index: CARDINAL): BOOLEAN;
  436. (* looks for the CommandBeginStr and if found, returns:
  437. TRUE, line found on & index past the end of line
  438. else
  439. RETURNS false & line started on & ending index of line. *)
  440. VAR
  441. StartLine, LstLngth, TypeCode: CARDINAL;
  442. BEGIN
  443. StartLine := line;
  444. LstLngth := GenLists.ListLength(InListGlobal);
  445. WHILE (line <= LstLngth) DO
  446. GenLists.GetElmt( InListGlobal, line, Parser.TheLine, TypeCode);
  447. IF PosUtils.Present( CommandBeginStr, Parser.TheLine) THEN
  448. (* found command begin string, so start on next line *)
  449. index := HIGH( Parser.TheLine)+1;
  450. RETURN TRUE;
  451. END;
  452. INC( line);
  453. END;
  454. (* if didn't find cmdbgnstr, go back to starting place *)
  455. line := StartLine;
  456. GenLists.GetElmt( InListGlobal, line, Parser.TheLine, TypeCode);
  457. index := HIGH( Parser.TheLine)+1;
  458. RETURN FALSE;
  459. END FindCmdBegin;
  460. PROCEDURE SetToDefaultColors( VAR FrameRec: ScrnTypes.PackedFrameRec );
  461. BEGIN
  462. WITH FrameRec DO
  463. normatrb := DefaultAtrb;
  464. normfor := DefaultFore;
  465. normbak := DefaultBack;
  466. (* Normal text *)
  467. bordatrb := DefaultBordatrb;
  468. bordfor := DefaultBordfor;
  469. bordbak := DefaultBordbak;
  470. (* Border colors *)
  471. selatrb := DefaultSelatrb;
  472. selfor := DefaultSelfor;
  473. selbak := DefaultSelbak;
  474. (* Selected text *)
  475. pbatrb := DefaultPbatrb;
  476. pbfor := DefaultPbfor;
  477. pbbak := DefaultPbbak;
  478. (* Pointer Bar Colors *)
  479. msgatrb := DefaultMsgatrb;
  480. msgfor := DefaultMsgfor;
  481. msgbak := DefaultMsgbak;
  482. (* Message Box Colors *)
  483. promatrb := DefaultPromatrb;
  484. promfor := DefaultPromfor;
  485. prombak := DefaultPrombak;
  486. (* Prompt Line Colors *)
  487. END;
  488. END SetToDefaultColors;
  489. PROCEDURE InitOutLists();
  490. (* initialize the output genlists *)
  491. BEGIN
  492. GenLists.NewList( DataList);
  493. GenLists.NewList( PromptList);
  494. GenLists.NewList( HelpList);
  495. GenLists.NewList( EdList);
  496. GenLists.NewList( FieldList);
  497. GenLists.NewList( ImageList);
  498. GenLists.NilList( LinkedFrames );
  499. WITH FrameRec DO
  500. ClearFirst := TRUE;
  501. ClearAfter := FALSE;
  502. EntryBox := VWindows.DoubleBox;
  503. ExitBox := VWindows.SingleBox;
  504. Caption[0] := 0C;
  505. VirtualWidth := 0;
  506. VirtualHeight := 0;
  507. startcol := 0;
  508. endcol := 255;
  509. startrow := 0;
  510. endrow := 255;
  511. headline := 0;
  512. action := "I";
  513. END;
  514. SetToDefaultColors( FrameRec );
  515. StrEdit.SetLength( HelpFrame, 0);
  516. StrEdit.SetLength( ParentFrame, 0);
  517. StrEdit.SetLength( NormalNextFrame, 0);
  518. StrEdit.SetLength( FrameAbove, 0 );
  519. StrEdit.SetLength( FrameBelow, 0 );
  520. StrEdit.SetLength( FrameLeft, 0 );
  521. StrEdit.SetLength( FrameRight, 0 );
  522. END InitOutLists;
  523. PROCEDURE GetAFrameName( VAR TheFrame: ARRAY OF CHAR): BOOLEAN;
  524. (* gets the frame key as the next word, if the terminator is OK *)
  525. VAR
  526. tmpstr : ARRAY [0..79] OF CHAR;
  527. BEGIN
  528. IF (Terminator = ":") THEN
  529. NextWord( tmpstr, Terminator);
  530. IF M2Strings.Length(tmpstr) < HIGH(TheFrame) THEN
  531. M2Strings.Assign( tmpstr, TheFrame );
  532. RETURN TRUE;
  533. END;
  534. END;
  535. RETURN FALSE;
  536. END GetAFrameName;
  537. PROCEDURE ListStartOK(): BOOLEAN;
  538. (* checks to see if we are at the valid start of a command
  539. area: we must have a ":" and a "{" next *)
  540. VAR
  541. tmpword: ARRAY [0..80] OF CHAR;
  542. BEGIN
  543. IF (Terminator = ":") THEN
  544. NextCrunchedWord( tmpword, Terminator );
  545. RETURN (M2Strings.Length( tmpword) = 0) AND
  546. (Terminator = "{");
  547. END;
  548. RETURN FALSE;
  549. END ListStartOK;
  550. PROCEDURE GetList( VAR OutList: GenLists.GenList): BOOLEAN;
  551. (* puts the following lines in a genlist, until a "}" is
  552. reached *)
  553. VAR
  554. type: CARDINAL;
  555. stop: BOOLEAN;
  556. BEGIN
  557. IF ListStartOK() THEN
  558. stop := FALSE;
  559. REPEAT
  560. INC( CurrentLine);
  561. IF CurrentLine > GenLists.ListLength( InListGlobal) THEN
  562. RETURN ReportErr( SectnEndErr);
  563. END;
  564. GenLists.GetElmt( InListGlobal, CurrentLine, Parser.TheLine, type);
  565. IF (M2Strings.Length( Parser.TheLine) > 0) AND
  566. (Parser.TheLine[0] = SectnEnd) THEN
  567. stop := TRUE;
  568. ELSIF LastChar( Parser.TheLine) = SectnEnd THEN
  569. M2Strings.Delete( Parser.TheLine,
  570. M2Strings.Length(Parser.TheLine) - 1, 1);
  571. stop := TRUE;
  572. GenLists.ListInsert( Parser.TheLine, GenLists.StrCode,
  573. OutList, AfterLastElmt);
  574. ELSE
  575. GenLists.ListInsert( Parser.TheLine, GenLists.StrCode,
  576. OutList, AfterLastElmt);
  577. END;
  578. UNTIL stop;
  579. (* set CurrentIndex high so GetNextWord will go to the next
  580. line next time. *)
  581. CurrentIndex := HIGH( Parser.TheLine) + 1;
  582. RETURN TRUE;
  583. ELSE
  584. RETURN FALSE;
  585. END;
  586. END GetList;
  587. PROCEDURE GetFieldMark( Terminator: CHAR): BOOLEAN;
  588. (* reads a new field delimiter for use in the display section *)
  589. BEGIN
  590. IF (Terminator = ":") THEN
  591. NextWord( CurrentWord, Terminator);
  592. IF M2Strings.Length( CurrentWord) = 0 THEN
  593. (*They're using a terminator as a field mark.*)
  594. IF (Terminator # ' ') AND (Terminator # EOL) THEN
  595. FieldMark := Terminator;
  596. ELSE
  597. RETURN FALSE;
  598. END;
  599. GetNextSep( Terminator );
  600. (*They may or may not have '; replace' after FieldMark
  601. command. This skips it if it's there, and leaves
  602. CurrentIndex on the EOL if not.*)
  603. ELSIF M2Strings.Length( CurrentWord) = 1 THEN
  604. FieldMark := CurrentWord[0];
  605. ELSE
  606. RETURN FALSE;
  607. END;
  608. ELSE
  609. RETURN FALSE;
  610. END;
  611. RETURN TRUE;
  612. END GetFieldMark;
  613. PROCEDURE CheckHelpFrame();
  614. (* if the help string is only a single word short enough to be
  615. a AFrameName, it is used as the HelpFrame, not a help list *)
  616. VAR
  617. line: ARRAY [0..255] OF CHAR;
  618. lngth, type: CARDINAL;
  619. BEGIN
  620. lngth := GenLists.ListLength( HelpList);
  621. IF (lngth <= 2) THEN
  622. GenLists.GetElmt( HelpList, 1, line, type);
  623. StrEdit.CrunchBlanks( line);
  624. StrEdit.DeleteChar( '}', line );
  625. IF (NOT PosUtils.Present( blank, line)) AND
  626. (M2Strings.Length( line) <= NdxTypes.RecNameLength) THEN
  627. M2Strings.Assign( line, HelpFrame);
  628. GenLists.ListDelete( HelpList, 1, 1);
  629. END;
  630. END;
  631. END CheckHelpFrame;
  632. PROCEDURE SetColorBase( fore, back : MsColors.AColor; attrib:
  633. MsColors.AMonoAttribute);
  634. (* sets a new normal color & attribute, which are kept at the
  635. bottom of the color stack *)
  636. BEGIN
  637. ColorBase.forec := fore;
  638. ColorBase.backc := back;
  639. IF attrib <> MsColors.invisible THEN
  640. ColorBase.atrbc := attrib;
  641. END;
  642. END SetColorBase;
  643. PROCEDURE GetColor( VAR forecolr, backcolr: MsColors.AColor; VAR atrbut:
  644. MsColors.AMonoAttribute): BOOLEAN;
  645. (* decode the following words as colors and attributes *)
  646. VAR
  647. colorord: CARDINAL;
  648. term1 : CHAR;
  649. BEGIN
  650. NextWordCap( CurrentWord, Terminator);
  651. (* get past the "(" *)
  652. IF (M2Strings.Length( CurrentWord) # 0) OR
  653. (Terminator # '(') THEN
  654. RETURN ReportErr( CoFormErr);
  655. END;
  656. NextWordCap( CurrentWord, Terminator);
  657. (* get the 1st color number *)
  658. IF NOT GetColorNum( CurrentWord, colorord ) THEN
  659. RETURN FALSE;
  660. END;
  661. forecolr := VAL( MsColors.AColor, colorord);
  662. (* next, decode background *)
  663. term1 := Terminator;
  664. NextWordCap( CurrentWord, Terminator);
  665. (* get the 2nd color number *)
  666. IF (term1 # ',') OR
  667. (Terminator # ')') THEN
  668. RETURN ReportErr( CoFormErr);
  669. END;
  670. IF NOT GetColorNum( CurrentWord, colorord ) THEN
  671. RETURN FALSE;
  672. END;
  673. backcolr := VAL( MsColors.AColor, colorord);
  674. (* next, decode monochrome attribute *)
  675. GetNextSep( Terminator);
  676. (* see if there is a mono attrib *)
  677. IF Terminator # EOL THEN
  678. (* there is a mono attribute specified *)
  679. NextCrunchedWord( CurrentWord, Terminator);
  680. IF (Terminator # EOL) THEN
  681. (* the mono attrib should be the last word on the line *)
  682. RETURN ReportErr( CoFormErr);
  683. END;
  684. IF NOT NameToAttrib( CurrentWord, atrbut) THEN
  685. RETURN ReportErr( CoFormErr);
  686. END;
  687. END;
  688. RETURN TRUE;
  689. END GetColor;
  690. PROCEDURE DoColorChar( colorchar: CHAR) : BOOLEAN;
  691. (* add the following character to the defined global color codes *)
  692. VAR
  693. poscnt: CARDINAL;
  694. for1, back1: MsColors.AColor;
  695. atrb1: MsColors.AMonoAttribute;
  696. BEGIN
  697. poscnt := PosUtils.Pos( colorchar, ColorKeys);
  698. IF poscnt > HIGH( ColorKeys) THEN
  699. (* color character is new *)
  700. poscnt := M2Strings.Length(ColorKeys);
  701. StrEdit.Append( ColorKeys, colorchar);
  702. KeyAtrbs[poscnt] := DefaultAtrb;
  703. END;
  704. IF NOT GetColor( for1, back1, atrb1) THEN
  705. RETURN FALSE;
  706. END;
  707. (* decode foreground and background *)
  708. KeyFors[poscnt] := for1;
  709. KeyBacks[poscnt] := back1;
  710. IF atrb1 <> MsColors.invisible THEN
  711. (* if an attribute specified, replace attribute *)
  712. KeyAtrbs[poscnt] := atrb1;
  713. END;
  714. RETURN TRUE;
  715. END DoColorChar;
  716. PROCEDURE DoColors() : BOOLEAN;
  717. (* process the color command section *)
  718. VAR
  719. for1, back1 : MsColors.AColor;
  720. atrb1: MsColors.AMonoAttribute;
  721. BEGIN
  722. IF NOT ListStartOK() THEN
  723. RETURN ReportErr( SectnErr);
  724. END;
  725. REPEAT
  726. NextCrunchedWord( CurrentWord, Terminator);
  727. IF (Terminator # "=") AND
  728. (Terminator # blank) AND
  729. (Terminator # SectnEnd) THEN
  730. RETURN ReportErr( CoEqErr);
  731. END;
  732. IF PosUtils.Equal( CurrentWord, 'BORDER') THEN
  733. IF NOT GetColor( for1, back1, atrb1) THEN
  734. RETURN FALSE;
  735. END;
  736. DefaultBordatrb := atrb1;
  737. DefaultBordfor := for1;
  738. DefaultBordbak := back1;
  739. ELSIF PosUtils.Equal(CurrentWord, 'SELECTEDTEXT') THEN
  740. IF NOT GetColor( for1, back1, atrb1) THEN
  741. RETURN FALSE;
  742. END;
  743. DefaultSelatrb := atrb1;
  744. DefaultSelfor := for1;
  745. DefaultSelbak := back1;
  746. ELSIF PosUtils.Equal(CurrentWord, 'NORMALTEXT') THEN
  747. IF NOT GetColor( for1, back1, atrb1) THEN
  748. RETURN FALSE;
  749. END;
  750. DefaultAtrb := atrb1;
  751. DefaultFore := for1;
  752. DefaultBack := back1;
  753. SetColorBase( for1, back1, atrb1);
  754. (* We are changing the normal colors, so change the
  755. colorstack appropriately *)
  756. ELSIF PosUtils.Equal(CurrentWord, 'POINTERBAR') THEN
  757. IF NOT GetColor( for1, back1, atrb1) THEN
  758. RETURN FALSE;
  759. END;
  760. DefaultPbatrb := atrb1;
  761. DefaultPbfor := for1;
  762. DefaultPbbak := back1;
  763. ELSIF PosUtils.Equal(CurrentWord, 'MESSAGES') THEN
  764. IF NOT GetColor( for1, back1, atrb1) THEN
  765. RETURN FALSE;
  766. END;
  767. DefaultMsgatrb := atrb1;
  768. DefaultMsgfor := for1;
  769. DefaultMsgbak := back1;
  770. ELSIF PosUtils.Equal(CurrentWord, 'PROMPTS') THEN
  771. IF NOT GetColor( for1, back1, atrb1) THEN
  772. RETURN FALSE;
  773. END;
  774. DefaultPromatrb := atrb1;
  775. DefaultPromfor := for1;
  776. DefaultPrombak := back1;
  777. ELSIF M2Strings.Length(CurrentWord) = 1 THEN
  778. (* defining a new color code char *)
  779. IF NOT DoColorChar( CurrentWord[0]) THEN
  780. RETURN FALSE;
  781. END;
  782. ELSIF M2Strings.Length(CurrentWord) = 0 THEN
  783. (* do nothing unless hit end of list *)
  784. IF Terminator = EOF THEN
  785. RETURN ReportErr( SectnEndErr);
  786. END;
  787. ELSE
  788. RETURN ReportErr( CoFormErr);
  789. END;
  790. UNTIL Terminator = SectnEnd;
  791. RETURN TRUE;
  792. END DoColors;
  793. PROCEDURE DoWindow() : BOOLEAN;
  794. (* process the window comand section *)
  795. PROCEDURE NextNumSubOne( VAR result: CARDINAL): BOOLEAN;
  796. (* convert the next word to a number and subtract one *)
  797. BEGIN
  798. IF (NOT NextNum( result)) OR
  799. (result = 0) THEN
  800. RETURN FALSE;
  801. END;
  802. DEC( result);
  803. RETURN TRUE;
  804. END NextNumSubOne;
  805. BEGIN
  806. (* DoWindow *)
  807. IF NOT ListStartOK() THEN
  808. RETURN ReportErr( SectnErr);
  809. END;
  810. REPEAT
  811. NextCrunchedWord( CurrentWord, Terminator);
  812. IF PosUtils.Equal( CurrentWord, 'POSITION') THEN
  813. IF Terminator # ":" THEN
  814. RETURN ReportErr( NeedColon);
  815. END;
  816. NextWordCap( CurrentWord, Terminator);
  817. WITH FrameRec DO
  818. IF (Terminator # "(") OR
  819. (NOT NextNumSubOne( startcol)) OR
  820. (Terminator # ",") OR
  821. (NOT NextNumSubOne( startrow)) OR
  822. (Terminator # ",") OR
  823. (NOT NextNumSubOne( endcol)) OR
  824. (Terminator # ",") OR
  825. (NOT NextNumSubOne( endrow)) OR
  826. (Terminator # ")") THEN
  827. RETURN ReportErr( NumSepErr);
  828. END;
  829. IF (startcol > endcol) OR
  830. (startrow > endrow) THEN
  831. RETURN ReportErr( CornerErr);
  832. END;
  833. (* WindowHite := endrow - startrow; no longer used *)
  834. END;
  835. ELSIF PosUtils.Equal(CurrentWord, 'NOBOX') THEN
  836. LowLevel.Fill( SYSTEM.ADR(FrameRec.EntryBox),
  837. SYSTEM.TSIZE(VWindows.BoxStr), 0C );
  838. LowLevel.Fill( SYSTEM.ADR(FrameRec.ExitBox),
  839. SYSTEM.TSIZE(VWindows.BoxStr), 0C );
  840. (*Null it completely out to prevent confusion when
  841. we look at raw .DSP file dumps.*)
  842. ELSIF PosUtils.Equal(CurrentWord, 'SINGLEBOX') THEN
  843. FrameRec.ExitBox := VWindows.SingleBox;
  844. FrameRec.EntryBox := VWindows.SingleBox;
  845. ELSIF PosUtils.Equal(CurrentWord, 'DOUBLEBOX') THEN
  846. FrameRec.ExitBox := VWindows.SingleBox;
  847. FrameRec.EntryBox := VWindows.DoubleBox;
  848. ELSIF PosUtils.Equal(CurrentWord, 'ENTRYBOX') THEN
  849. IF Terminator = EOL THEN
  850. LowLevel.Fill( SYSTEM.ADR(FrameRec.EntryBox),
  851. SYSTEM.TSIZE(VWindows.BoxStr), 0C );
  852. ELSE
  853. NextWordCap( FrameRec.EntryBox, Terminator );
  854. END;
  855. ELSIF PosUtils.Equal(CurrentWord, 'EXITBOX') THEN
  856. IF Terminator = EOL THEN
  857. LowLevel.Fill( SYSTEM.ADR(FrameRec.ExitBox),
  858. SYSTEM.TSIZE(VWindows.BoxStr), 0C );
  859. ELSE
  860. NextWordCap( FrameRec.ExitBox, Terminator );
  861. END;
  862. ELSIF PosUtils.Equal(CurrentWord, 'CAPTION') THEN
  863. IF Terminator = EOL THEN
  864. FrameRec.Caption[0] := 0C;
  865. ELSE
  866. NextWord(FrameRec.Caption, Terminator );
  867. (* We call NextWord directly to preserve case
  868. and spacing in the caption. *)
  869. END;
  870. ELSIF PosUtils.Equal(CurrentWord, 'OVERLAY') THEN
  871. FrameRec.ClearFirst := FALSE;
  872. ELSIF PosUtils.Equal(CurrentWord, 'CLEARFIRST') THEN
  873. FrameRec.ClearFirst := TRUE;
  874. ELSIF PosUtils.Equal(CurrentWord, 'CLEARAFTER') THEN
  875. FrameRec.ClearAfter := TRUE;
  876. ELSIF PosUtils.Equal(CurrentWord, 'HEADINGLINE') OR
  877. PosUtils.Equal(CurrentWord, 'HEADING') THEN
  878. IF Terminator # ":" THEN
  879. RETURN ReportErr( NeedColon);
  880. END;
  881. IF (NOT NextNum( FrameRec.headline)) THEN
  882. RETURN ReportErr( NumSepErr);
  883. END;
  884. ELSIF (M2Strings.Length(CurrentWord) = 0) THEN
  885. (* do nothing unless at end of list *)
  886. IF Terminator = EOF THEN
  887. RETURN ReportErr( SectnEndErr);
  888. END;
  889. ELSE
  890. RETURN ReportErr( WinFormErr);
  891. END;
  892. (* Since we are assuming at this point a command has completed we
  893. will move past any comments etc on the rest of the line *)
  894. IF Terminator # EOL THEN
  895. CurrentIndex:=M2Strings.Length(Parser.TheLine)
  896. END;
  897. UNTIL Terminator = SectnEnd;
  898. RETURN TRUE;
  899. END DoWindow;
  900. PROCEDURE InitFieldRec( VAR FieldRec: ScrnTypes.InputFieldRecord);
  901. (* initializes the field record *)
  902. BEGIN
  903. LowLevel.Fill( SYSTEM.ADR(FieldRec), ByteFiddler.Size(FieldRec), 0C );
  904. END InitFieldRec;
  905. PROCEDURE InitImageRec( VAR ImageRec: ScrnTypes.ImageElement );
  906. BEGIN
  907. LowLevel.Fill( SYSTEM.ADR(ImageRec), ByteFiddler.Size(ImageRec), 0C );
  908. ImageRec.row := 1;
  909. ImageRec.col := 1;
  910. END InitImageRec;
  911. PROCEDURE GetSelector( VAR sel : CARDINAL) : BOOLEAN;
  912. (* parses field for menu select character *)
  913. BEGIN
  914. NextWordCap( CurrentWord, Terminator);
  915. IF (M2Strings.Length( CurrentWord) > 0) OR (Terminator # "(") THEN
  916. IF Terminator = SectnEnd THEN
  917. (* at the end of Fields section *)
  918. RETURN FALSE;
  919. ELSE
  920. RETURN ReportErr( NeedParen);
  921. END;
  922. END;
  923. NextWord( CurrentWord, Terminator );
  924. (*We use GetNextWord instead of NextWordCap to preserve case
  925. of the select char.*)
  926. IF (M2Strings.Length( CurrentWord) > 1) OR (Terminator # ")") THEN
  927. IF NOT StrConv.StrToCardinal( CurrentWord, 0, sel ) THEN
  928. (*This lets us use extended keys as selectors.*)
  929. RETURN ReportErr( SelectorErr);
  930. ELSE
  931. RETURN TRUE;
  932. END;
  933. END;
  934. IF M2Strings.Length( CurrentWord) = 1 THEN
  935. (* the menu selector key, if specified for this field *)
  936. sel := ORD( CurrentWord[0]);
  937. ELSE
  938. sel := 0;
  939. END;
  940. RETURN TRUE;
  941. END GetSelector;
  942. PROCEDURE GetInteger( VAR FieldRec: ScrnTypes.InputFieldRecord) : BOOLEAN;
  943. BEGIN
  944. FieldRec.typ := ScrnTypes.IntCode;
  945. IF (Terminator # "[") THEN
  946. RETURN ReportErr( NeedBracket);
  947. END;
  948. NextWordCap( CurrentWord, Terminator);
  949. IF (CurrentWord[0] = 0C) AND (Terminator = "-") THEN
  950. (*The lower bound is negative.*)
  951. NextWordCap( CurrentWord, Terminator );
  952. M2Strings.Insert( "-", CurrentWord, 0 );
  953. END;
  954. IF (Terminator = ".") THEN
  955. (*The bounds are separated with .. instead of - .*)
  956. GetNextSep( Terminator );
  957. IF (Terminator # ".") THEN
  958. RETURN ReportErr( NumSepErr);
  959. END;
  960. END;
  961. IF NOT (StrConv.StrToLongInteger( CurrentWord, 0, FieldRec.iMin)) THEN
  962. RETURN ReportErr( NumSepErr);
  963. END;
  964. NextWordCap( CurrentWord, Terminator);
  965. IF (CurrentWord[0] = 0C) AND (Terminator = "-") THEN
  966. (*The upper bound is negative.*)
  967. NextWordCap( CurrentWord, Terminator );
  968. M2Strings.Insert( "-", CurrentWord, 0 );
  969. END;
  970. IF NOT (StrConv.StrToLongInteger( CurrentWord, 0, FieldRec.iMax)) AND
  971. (Terminator = "]") THEN
  972. RETURN ReportErr( NeedBracket);
  973. END;
  974. GetNextSep( Terminator);
  975. (* move separator past the ] *)
  976. RETURN TRUE;
  977. END GetInteger;
  978. PROCEDURE GetReal( VAR FieldRec: ScrnTypes.InputFieldRecord) : BOOLEAN;
  979. BEGIN
  980. IF (Terminator # "[") THEN
  981. RETURN ReportErr( NeedBracket);
  982. END;
  983. IF NOT StrCnv1.GetEmbeddedReal( Parser.TheLine, CurrentIndex,
  984. FieldRec.rMin ) THEN
  985. RETURN ReportErr( NumSepErr );
  986. END;
  987. (* CurrentIndex should now be sitting on whatever follows the first
  988. number -- probably a space, maybe a '.' or a '-'. *)
  989. IF Parser.TheLine[ CurrentIndex ] = ' ' THEN
  990. GetNextSep( Terminator);
  991. ELSE
  992. INC( CurrentIndex );
  993. END;
  994. (* CurrentIndex is now sitting on the character following
  995. the first character of the separator. *)
  996. IF Parser.TheLine[ CurrentIndex ] = '.' THEN
  997. (* Don't start looking for the next number in the middle of
  998. the .. separator. *)
  999. INC( CurrentIndex );
  1000. END;
  1001. IF NOT StrCnv1.GetEmbeddedReal( Parser.TheLine, CurrentIndex,
  1002. FieldRec.rMax ) THEN
  1003. RETURN ReportErr( NumSepErr );
  1004. END;
  1005. GetNextSep( Terminator);
  1006. IF (Terminator # "]") THEN
  1007. RETURN ReportErr( NumSepErr);
  1008. END;
  1009. GetNextSep( Terminator);
  1010. (* move separator past the ] *)
  1011. RETURN TRUE;
  1012. END GetReal;
  1013. PROCEDURE GetEdField( VAR FieldRec: ScrnTypes.InputFieldRecord) : BOOLEAN;
  1014. VAR
  1015. TmpEdList: GenLists.GenList;
  1016. BEGIN
  1017. FieldRec.typ := ScrnTypes.EditorCode;
  1018. NextWordCap( CurrentWord, Terminator);
  1019. IF NOT (StrConv.StrToCardinal( CurrentWord, 0, FieldRec.Row2) AND
  1020. (* Row2 is the number of lines now; we will correct it to
  1021. the ending virtual row number when we process the image
  1022. and find out what row it starts on. *)
  1023. (Terminator = blank)) THEN
  1024. RETURN ReportErr( EdErr);
  1025. END;
  1026. NextWordCap( CurrentWord, Terminator);
  1027. IF NOT (PosUtils.Equal( CurrentWord, "LINES") OR
  1028. PosUtils.Equal( CurrentWord, "LINE")) THEN
  1029. RETURN ReportErr( EdErr);
  1030. END;
  1031. FieldRec.TextRow1 := 0;
  1032. FieldRec.CursorCol := 1;
  1033. FieldRec.CursorRow := 1;
  1034. FieldRec.MaxLines := 0;
  1035. FieldRec.ChangeMade := FALSE;
  1036. FieldRec.ReadOnly := FALSE;
  1037. GenLists.NewList( TmpEdList);
  1038. GenLists.ListInsert( TmpEdList, GenLists.ListCode, EdList, AfterLastElmt);
  1039. FieldRec.EdFieldNum := GenLists.ListLength( EdList);
  1040. RETURN TRUE;
  1041. END GetEdField;
  1042. PROCEDURE GetFieldData( VAR FieldRec: ScrnTypes.InputFieldRecord ): BOOLEAN;
  1043. (* This lets you put the word 'data' somewhere in the list of
  1044. field attributes in the same way that you put 'prompt' there
  1045. in releases preceding 1.5d. GetFieldData appends the fieldname to
  1046. the frame's DataList, and then looks for the next
  1047. line that contains an opening brace, and puts it plus all
  1048. lines that follow it up to the matching closing brace into a
  1049. TmpList, which it then appends to the end of the frame's
  1050. DataList. This means you can find the data associated with a
  1051. particular field by starting at the end of the frame's
  1052. DataList. Any time you find an element that is a list, you
  1053. look at the preceding element of the frame's DataList to see if it
  1054. contains the field name in which you are interested. If it
  1055. does, the elements of the sublist will be the
  1056. strings retrieved by GetFieldData. We use it for things
  1057. like initialization of Editor fields and storage of
  1058. StrLogic expressions. *)
  1059. VAR
  1060. TmpList: GenLists.GenList;
  1061. BraceCount : INTEGER;
  1062. StartFound, EndFound : BOOLEAN;
  1063. TypeCode : CARDINAL;
  1064. BEGIN
  1065. BraceCount := 0;
  1066. StartFound := FALSE;
  1067. EndFound := FALSE;
  1068. GenLists.NewList( TmpList );
  1069. REPEAT
  1070. INC( CurrentLine);
  1071. IF CurrentLine < GenLists.ListLength( InListGlobal) THEN
  1072. GenLists.GetElmt( InListGlobal, CurrentLine, Parser.TheLine, TypeCode );
  1073. EnclosureCount( '{', '}', Parser.TheLine, BraceCount, StartFound,
  1074. EndFound, TRUE );
  1075. IF StartFound THEN
  1076. GenLists.ListInsert( Parser.TheLine, GenLists.StrCode,
  1077. TmpList, AfterLastElmt);
  1078. END;
  1079. ELSE
  1080. RETURN ReportErr( DataErr);
  1081. END;
  1082. UNTIL EndFound;
  1083. GenLists.ListInsert( FieldRec.fnam, GenLists.StrCode, DataList,
  1084. AfterLastElmt );
  1085. (* We insert the field name as the preceding element of the DataList
  1086. so that users will be able to find the data associated with
  1087. a particular field by looking for its name. *)
  1088. GenLists.ListInsert( TmpList, GenLists.ListCode, DataList, AfterLastElmt );
  1089. CurrentIndex := M2Strings.Length( Parser.TheLine);
  1090. RETURN TRUE;
  1091. END GetFieldData;
  1092. PROCEDURE GetFieldOptions( VAR FieldRec: ScrnTypes.InputFieldRecord) : BOOLEAN;
  1093. VAR
  1094. DataFound, PromptFound : BOOLEAN;
  1095. type : CARDINAL;
  1096. BEGIN
  1097. PromptFound := FALSE;
  1098. DataFound := FALSE;
  1099. IF Terminator = SectnEnd THEN
  1100. RETURN TRUE;
  1101. END;
  1102. REPEAT
  1103. GetNextSep( Terminator);
  1104. IF Terminator # EOL THEN
  1105. NextWordCap( CurrentWord, Terminator);
  1106. IF PosUtils.Equal(CurrentWord, 'REQUIRED') THEN
  1107. FieldRec.req := TRUE;
  1108. ELSIF PosUtils.Equal(CurrentWord, 'PROMPT') THEN
  1109. PromptFound := TRUE;
  1110. Terminator:=EOL;
  1111. ELSIF PosUtils.Equal(CurrentWord, 'DATA') THEN
  1112. DataFound := TRUE;
  1113. ELSIF PosUtils.Equal(CurrentWord, 'HELP') THEN
  1114. IF Terminator = EOL THEN
  1115. RETURN ReportErr( HelpFErr);
  1116. END;
  1117. NextWord( FieldRec.HelpFrame, Terminator );
  1118. (*Changed on 23 Apr 88: use GetNextWord to preserve case
  1119. sensitivity.*)
  1120. ELSIF FieldRec.typ = ScrnTypes.EditorCode THEN
  1121. IF PosUtils.Equal( CurrentWord, "READONLY" ) THEN
  1122. FieldRec.ReadOnly := TRUE;
  1123. ELSIF PosUtils.Equal( CurrentWord, "MAXLINES" ) THEN
  1124. IF NOT NextNum( FieldRec.MaxLines ) THEN
  1125. FieldRec.MaxLines := 0;
  1126. RETURN ReportErr( EdErr );
  1127. END;
  1128. END;
  1129. END;
  1130. END;
  1131. UNTIL (Terminator = EOL) OR (Terminator = SectnEnd) OR
  1132. (Terminator = EOF);
  1133. IF PromptFound THEN
  1134. (* add the prompt to the prompt list *)
  1135. IF Terminator = SectnEnd THEN
  1136. RETURN FALSE;
  1137. END;
  1138. INC( CurrentLine);
  1139. IF CurrentLine < GenLists.ListLength( InListGlobal) THEN
  1140. GenLists.GetElmt( InListGlobal, CurrentLine, Parser.TheLine, type);
  1141. GenLists.ListInsert( Parser.TheLine, GenLists.StrCode,
  1142. PromptList, AfterLastElmt);
  1143. FieldRec.PromptNum := GenLists.ListLength( PromptList);
  1144. ELSE
  1145. RETURN ReportErr( PromptErr);
  1146. END;
  1147. CurrentIndex := M2Strings.Length( Parser.TheLine);
  1148. END;
  1149. IF DataFound THEN
  1150. IF Terminator = SectnEnd THEN
  1151. RETURN FALSE;
  1152. END;
  1153. IF NOT GetFieldData( FieldRec ) THEN
  1154. RETURN FALSE;
  1155. END;
  1156. END;
  1157. RETURN TRUE;
  1158. END GetFieldOptions;
  1159. PROCEDURE DoFields() : BOOLEAN;
  1160. (* process the Fields section of the command area *)
  1161. VAR
  1162. FieldRec: ScrnTypes.InputFieldRecord;
  1163. DummyDspFile: ScrnTypes.DisplayFile;
  1164. selector, GroupCounter, GroupMax: CARDINAL;
  1165. GroupHeader: BOOLEAN;
  1166. realDecPlaces : CARDINAL; (* JDM/MBC *)
  1167. BEGIN
  1168. IF NOT ListStartOK() THEN
  1169. RETURN ReportErr( SectnErr);
  1170. END;
  1171. GroupMax := 0;
  1172. REPEAT
  1173. GroupHeader := FALSE;
  1174. InitFieldRec( FieldRec);
  1175. IF NOT GetSelector( selector) THEN
  1176. IF M2Strings.Length( ErrStrGlobal) = 0 THEN
  1177. RETURN TRUE;
  1178. ELSE
  1179. RETURN FALSE;
  1180. END;
  1181. END;
  1182. (*
  1183. NextWordCap( CurrentWord, Terminator);
  1184. (* space between ) and ' *)
  1185. IF (M2Strings.Length( CurrentWord) > 0) OR (Terminator # "'") THEN
  1186. RETURN ReportErr( NeedQuote);
  1187. END;
  1188. *)
  1189. NextWordCap( FieldRec.fnam, Terminator);
  1190. (* get field name *)
  1191. IF Terminator # "'" THEN
  1192. RETURN ReportErr( NeedQuote);
  1193. END;
  1194. NextWordCap( CurrentWord, Terminator);
  1195. IF PosUtils.Equal( CurrentWord, 'STRING') THEN
  1196. FieldRec.typ := ScrnTypes.StringCode;
  1197. ELSIF PosUtils.Equal(CurrentWord, 'GOTO') THEN
  1198. FieldRec.typ := ScrnTypes.GotoCode;
  1199. FieldRec.MenuKey := selector;
  1200. NextWord( FieldRec.ReturnVal, Terminator );
  1201. (*Use GetNextWord to preserve case sensitivity.*)
  1202. ELSIF PosUtils.Equal(CurrentWord, 'INTEGER') THEN
  1203. IF NOT GetInteger( FieldRec) THEN
  1204. RETURN FALSE;
  1205. END;
  1206. ELSIF PosUtils.Equal(CurrentWord, 'REAL') THEN
  1207. (* We have to set the tag field before any of the variant
  1208. fields; Stony Brook is smart enough to check for consistency. *)
  1209. FieldRec.typ := ScrnTypes.RealCode;
  1210. IF Terminator = "." THEN
  1211. (* find and load the number of decimal places for the REAL *)
  1212. IF NOT NextNum( realDecPlaces ) THEN
  1213. RETURN ReportErr( NumSepErr );
  1214. ELSE
  1215. FieldRec.decimalPlace := VAL( ScrnTypes.DecimalPlaceType,
  1216. realDecPlaces );
  1217. END
  1218. ELSE
  1219. (* Signal that the default of user-specified dec. place used *)
  1220. FieldRec.decimalPlace := -1;
  1221. END;
  1222. IF NOT GetReal( FieldRec) THEN
  1223. RETURN FALSE;
  1224. END;
  1225. ELSIF PosUtils.Equal(CurrentWord, 'GROUP') THEN
  1226. GroupHeader := TRUE;
  1227. GroupCounter := 1;
  1228. IF (NOT NextNum( GroupMax)) OR
  1229. (GroupMax = 0) THEN
  1230. RETURN ReportErr( NumSepErr);
  1231. END;
  1232. ELSIF PosUtils.Equal(CurrentWord, 'CHOICE') THEN
  1233. IF (GroupMax = 0) THEN
  1234. (* error if didn't start a group first *)
  1235. RETURN ReportErr( GroupErr);
  1236. END;
  1237. FieldRec.typ := ScrnTypes.GroupMember;
  1238. FieldRec.ChoiceKey := selector;
  1239. FieldRec.GroupSize := GroupMax;
  1240. FieldRec.GroupID := GroupCounter;
  1241. FieldRec.selected := (GroupCounter = 1);
  1242. (* TRUE for first field *)
  1243. INC( GroupCounter);
  1244. IF (GroupMax < GroupCounter) THEN
  1245. (* at end of group, reset size to show no group is active *)
  1246. GroupMax := 0;
  1247. END;
  1248. ELSIF PosUtils.Equal(CurrentWord, 'EDITOR') THEN
  1249. IF NOT GetEdField( FieldRec) THEN
  1250. RETURN FALSE;
  1251. END;
  1252. ELSIF PosUtils.Equal(CurrentWord, 'DISPLAY') OR
  1253. PosUtils.Equal(CurrentWord, 'DISPLAYONLY') THEN
  1254. FieldRec.typ := ScrnTypes.DispCode;
  1255. ELSIF M2Strings.Length(CurrentWord) = 0 THEN
  1256. (* do nothing unless at end of list *)
  1257. IF Terminator = EOF THEN
  1258. RETURN ReportErr( SectnEndErr);
  1259. END;
  1260. ELSE
  1261. (* This is what allows you to have user-defined type names.*)
  1262. FieldRec.typ := FieldTypes.TypeCode( CurrentWord );
  1263. END;
  1264. IF NOT GroupHeader THEN
  1265. (* do not process options or save a field record for
  1266. group headers *)
  1267. IF NOT GetFieldOptions( FieldRec) THEN
  1268. RETURN FALSE;
  1269. END;
  1270. GenLists.ListInsert( FieldRec, RecType, FieldList, AfterLastElmt);
  1271. END;
  1272. UNTIL Terminator = SectnEnd;
  1273. RETURN TRUE;
  1274. END DoFields;
  1275. PROCEDURE DoCommandArea( VAR FrameName: ScrnTypes.AFrameName): BOOLEAN;
  1276. (* Processes the command area of the frame. FrameName is set to
  1277. the name of the frame processed. The other output is communicated
  1278. in the global variables that MakeOutList uses. *)
  1279. VAR
  1280. dumtype: CARDINAL;
  1281. BEGIN
  1282. ReplacingFieldMarks := FALSE;
  1283. NextWordCap( CurrentWord, Terminator);
  1284. (* We start by determining whether FrameName is inside or
  1285. outside the Command Area -- outside is the old syntax. *)
  1286. IF (Parser.TheLine[0] # BorderChar) OR
  1287. (M2Strings.Length(CurrentWord) # 0) THEN
  1288. FrameName[0] := 0C;
  1289. IF NOT FindCmdBegin( CurrentLine, CurrentIndex) THEN
  1290. RETURN ReportErr( FrameErr);
  1291. END;
  1292. ELSE
  1293. (* FrameName is outside the command area. *)
  1294. NextWord( CurrentWord, Terminator );
  1295. (* The frame name is next and it should be the last thing
  1296. on the line. We use GetNextWord to preserve case
  1297. sensitivity.*)
  1298. IF (Terminator # EOL) OR
  1299. (M2Strings.Length(CurrentWord) = 0) THEN
  1300. RETURN ReportErr( FrameNameErr);
  1301. END;
  1302. (* save name, which was CAPPED by NextWordCap() *)
  1303. M2Strings.Assign( CurrentWord, FrameName);
  1304. IF NOT FindCmdBegin( CurrentLine, CurrentIndex) THEN
  1305. (* continue only if find a command begin string *)
  1306. RETURN TRUE;
  1307. END;
  1308. END;
  1309. LOOP
  1310. NextCrunchedWord( CurrentWord, Terminator);
  1311. IF PosUtils.Equal( CurrentWord, 'PARENTFRAME' ) THEN
  1312. IF NOT GetAFrameName( ParentFrame) THEN
  1313. RETURN ReportErr( ParentErr);
  1314. END;
  1315. ELSIF PosUtils.Equal( CurrentWord, 'NORMALNEXT' ) THEN
  1316. IF NOT GetAFrameName( NormalNextFrame) THEN
  1317. RETURN ReportErr( NormalErr);
  1318. END;
  1319. ELSIF PosUtils.Equal( CurrentWord, 'FRAMEABOVE' ) THEN
  1320. IF NOT GetAFrameName( FrameAbove ) THEN
  1321. RETURN ReportErr( PlacementErr );
  1322. END;
  1323. ELSIF PosUtils.Equal( CurrentWord, 'FRAMEBELOW' ) THEN
  1324. IF NOT GetAFrameName( FrameBelow ) THEN
  1325. RETURN ReportErr( PlacementErr );
  1326. END;
  1327. ELSIF PosUtils.Equal( CurrentWord, 'FRAMELEFT' ) THEN
  1328. IF NOT GetAFrameName( FrameLeft ) THEN
  1329. RETURN ReportErr( PlacementErr );
  1330. END;
  1331. ELSIF PosUtils.Equal( CurrentWord, 'FRAMERIGHT' ) THEN
  1332. IF NOT GetAFrameName( FrameRight ) THEN
  1333. RETURN ReportErr( PlacementErr );
  1334. END;
  1335. ELSIF PosUtils.Equal( CurrentWord, 'FIELDMARK' ) THEN
  1336. IF NOT GetFieldMark( Terminator) THEN
  1337. RETURN ReportErr( FMErr);
  1338. END;
  1339. ELSIF PosUtils.Equal( CurrentWord, 'WINDOW' ) THEN
  1340. IF NOT DoWindow() THEN
  1341. RETURN FALSE;
  1342. END;
  1343. ELSIF PosUtils.Equal( CurrentWord, 'DATA' ) THEN
  1344. IF NOT GetList( DataList) THEN
  1345. RETURN ReportErr( DataErr);
  1346. END;
  1347. ELSIF PosUtils.Equal( CurrentWord, 'HELP' ) THEN
  1348. IF NOT GetList( HelpList) THEN
  1349. RETURN ReportErr( HelpErr);
  1350. END;
  1351. CheckHelpFrame();
  1352. ELSIF PosUtils.Equal( CurrentWord, 'COLORS' ) THEN
  1353. IF NOT DoColors() THEN
  1354. RETURN FALSE;
  1355. END;
  1356. ELSIF PosUtils.Equal( CurrentWord, 'FIELDS' ) THEN
  1357. IF NOT DoFields() THEN
  1358. RETURN FALSE;
  1359. END;
  1360. ELSIF PosUtils.Present( CommandEndStr, Parser.TheLine) THEN
  1361. IF FrameName[0] = 0C THEN
  1362. (*We never found a FrameName.*)
  1363. StrEdit.AssignStr( FrameNameErr, ErrStrGlobal );
  1364. RETURN FALSE;
  1365. END;
  1366. RETURN TRUE;
  1367. ELSIF (Parser.TheLine[0] = BorderChar) AND
  1368. (M2Strings.Length(CurrentWord) = 0) THEN
  1369. NextWord( CurrentWord, Terminator );
  1370. (* The frame name is next (and it should be the last thing
  1371. on the line); don't use NextWordCap because it caps, and
  1372. we want to be case sensitive with frame names. *)
  1373. IF (* (Terminator # EOL) OR JM 7/16/91 *)
  1374. (M2Strings.Length(CurrentWord) = 0) THEN
  1375. RETURN ReportErr( FrameNameErr);
  1376. END;
  1377. M2Strings.Assign( CurrentWord, FrameName);
  1378. (* Save name*)
  1379. ELSIF PosUtils.Equal( CurrentWord, 'HITANYKEY') THEN
  1380. FrameRec.action := "W";
  1381. ELSIF PosUtils.Equal( CurrentWord, 'DISPLAYONLY') THEN
  1382. FrameRec.action := "D";
  1383. ELSIF PosUtils.Equal( CurrentWord, 'INPUTSCREEN') THEN
  1384. FrameRec.action := "I";
  1385. ELSIF PosUtils.Equal( CurrentWord, 'REPLACE') THEN
  1386. ReplacingFieldMarks := TRUE;
  1387. ELSE
  1388. RETURN ReportErr( BadCommand);
  1389. END;
  1390. END;
  1391. END DoCommandArea;
  1392. PROCEDURE CheckFieldNumber();
  1393. (* check if same number of fields on screen as defined *)
  1394. BEGIN
  1395. IF FieldCount < GenLists.ListLength( FieldList) THEN
  1396. StrEdit.AssignStr( MoreErr, ErrStrGlobal);
  1397. BadLineGlobal := CurrentLine;
  1398. ELSIF FieldCount > GenLists.ListLength( FieldList) THEN
  1399. StrEdit.AssignStr( FewErr, ErrStrGlobal);
  1400. BadLineGlobal := CurrentLine;
  1401. (* ELSIF LineCount > (WindowHite + 1) THEN
  1402. AssignStr( 'Warning: screen may exceed window; scrolling may occur',
  1403. ErrStrGlobal); *)
  1404. END;
  1405. END CheckFieldNumber;
  1406. PROCEDURE AddToOutList(VAR line : ARRAY OF CHAR): BOOLEAN;
  1407. PROCEDURE HaveColor(): BOOLEAN;
  1408. BEGIN
  1409. (* is true if a color is turned on (we will store blanks) *)
  1410. RETURN(ColorStack^.prv <> NIL)
  1411. END HaveColor;
  1412. PROCEDURE AddColor( incode: CHAR; forcod, backcod: MsColors.AColor;
  1413. atrbcod: MsColors.AMonoAttribute);
  1414. BEGIN
  1415. VStorage.DosAlloc( ColorStack^.nxt, SYSTEM.TSIZE(CStack) );
  1416. ColorStack^.nxt^.prv := ColorStack;
  1417. ColorStack := ColorStack^.nxt;
  1418. ColorStack^.Ccode := incode;
  1419. ColorStack^.forec := forcod;
  1420. ColorStack^.backc := backcod;
  1421. ColorStack^.atrbc := atrbcod;
  1422. ColorStack^.nxt := NIL;
  1423. END AddColor;
  1424. PROCEDURE DeleteColor(): BOOLEAN;
  1425. BEGIN
  1426. IF ColorStack^.prv = NIL THEN
  1427. RETURN ReportErr( NestErr);
  1428. ELSE
  1429. ColorStack := ColorStack^.prv;
  1430. VStorage.DosDealloc( ColorStack^.nxt, SYSTEM.TSIZE(CStack) );
  1431. (* Note that this will never deallocate the
  1432. ColorBase, which is good since ColorBase is now
  1433. in the data segment. *)
  1434. ColorStack^.nxt := NIL;
  1435. RETURN TRUE;
  1436. END;
  1437. END DeleteColor;
  1438. VAR
  1439. InAField, firstcol, ColorChange : BOOLEAN;
  1440. LineLngth, indentation, i, WhichColor, BlanksInARow : CARDINAL;
  1441. ImageRec: ScrnTypes.ImageElement;
  1442. PROCEDURE AddRecord( VAR ImageRec: ScrnTypes.ImageElement);
  1443. VAR
  1444. FieldRec: ScrnTypes.InputFieldRecord;
  1445. TmpCol2, type: CARDINAL;
  1446. BEGIN
  1447. TmpCol2 := ImageRec.col + M2Strings.Length(
  1448. ImageRec.text) - 1;
  1449. IF (ImageRec.field > 0) THEN
  1450. (* save image list position in ImageNum field in field record *)
  1451. IF FieldCount > GenLists.ListLength( FieldList ) THEN
  1452. IF NOT ReportErr( FewErr ) THEN
  1453. END;
  1454. RETURN;
  1455. END;
  1456. GenLists.GetElmt( FieldList, FieldCount, FieldRec, type);
  1457. FieldRec.ImageNum := GenLists.ListLength( ImageList) + 1;
  1458. IF FieldRec.typ = ScrnTypes.EditorCode THEN
  1459. (* This editor field's width & height must be stored *)
  1460. INC( FieldRec.Row2, ImageRec.row - 1);
  1461. IF FieldRec.Row2 > FrameRec.VirtualHeight THEN
  1462. FrameRec.VirtualHeight := FieldRec.Row2;
  1463. END;
  1464. IF ReplacingFieldMarks THEN
  1465. FieldRec.Col2 := TmpCol2 + 1;
  1466. ELSE
  1467. FieldRec.Col2 := TmpCol2;
  1468. END;
  1469. IF FieldRec.Col2 > FrameRec.VirtualWidth THEN
  1470. FrameRec.VirtualWidth := FieldRec.Col2;
  1471. END;
  1472. END;
  1473. GenLists.ListReplace( FieldRec, type, FieldList, FieldCount);
  1474. END;
  1475. IF ImageRec.row > FrameRec.VirtualHeight THEN
  1476. FrameRec.VirtualHeight := ImageRec.row;
  1477. END;
  1478. IF TmpCol2 > FrameRec.VirtualWidth THEN
  1479. FrameRec.VirtualWidth := TmpCol2;
  1480. END;
  1481. ScrnUtl1.EncodeImageRec( ImageRec);
  1482. GenLists.ListInsert( ImageRec, GenLists.StrCode,
  1483. ImageList, AfterLastElmt);
  1484. END AddRecord;
  1485. PROCEDURE NewLineCheck();
  1486. VAR
  1487. BufChar : CHAR;
  1488. FieldRec: ScrnTypes.InputFieldRecord;
  1489. BEGIN
  1490. BufChar := line[indentation - 1];
  1491. WhichColor := PosUtils.Pos( BufChar, ColorKeys);
  1492. IF (BufChar = FieldMark) OR
  1493. (WhichColor <= HIGH(ColorKeys)) OR
  1494. ((BufChar = blank) AND (NOT ColorChange)) THEN
  1495. RETURN;
  1496. END;
  1497. IF firstcol THEN
  1498. (* in first column of new line *)
  1499. InitImageRec( ImageRec );
  1500. firstcol := FALSE;
  1501. ELSIF ((BlanksInARow>=3) AND (NOT HaveColor())) OR
  1502. ColorChange THEN
  1503. IF BlanksInARow >= 3 THEN
  1504. (* cut blanks from the end of the string *)
  1505. StrEdit.CutTrailingChars( blank, ImageRec.text);
  1506. END;
  1507. AddRecord( ImageRec);
  1508. InitImageRec( ImageRec );
  1509. ELSE
  1510. RETURN;
  1511. END;
  1512. WITH ImageRec DO
  1513. row := LineCount;
  1514. col := indentation;
  1515. foreg := ColorStack^.forec;
  1516. backg := ColorStack^.backc;
  1517. atrb := ColorStack^.atrbc;
  1518. IF InAField THEN
  1519. field := FieldCount;
  1520. ELSE
  1521. field := 0;
  1522. END;
  1523. END;
  1524. ColorChange := FALSE;
  1525. END NewLineCheck;
  1526. BEGIN
  1527. (*AddToOutList*)
  1528. IF PosUtils.IsBlank(line) THEN
  1529. RETURN TRUE;
  1530. END;
  1531. InAField := FALSE;
  1532. firstcol := TRUE;
  1533. ColorChange := FALSE;
  1534. BlanksInARow := 0;
  1535. indentation := 1;
  1536. LineLngth := M2Strings.Length( line);
  1537. InitImageRec( ImageRec );
  1538. WHILE indentation <= LineLngth DO
  1539. NewLineCheck();
  1540. IF line[indentation - 1]=FieldMark THEN
  1541. IF ColorStack^.Ccode = FieldMark THEN
  1542. (* if this mark is at end of a field *)
  1543. InAField := FALSE;
  1544. IF NOT DeleteColor() THEN
  1545. RETURN FALSE;
  1546. END;
  1547. ELSE
  1548. (* we are at the beginning of a field *)
  1549. AddColor( FieldMark, ColorStack^.forec,
  1550. ColorStack^.backc, ColorStack^.atrbc);
  1551. (* Use existing color for menu item *)
  1552. InAField := TRUE;
  1553. INC( FieldCount);
  1554. END;
  1555. IF ReplacingFieldMarks THEN
  1556. line[ indentation - 1] := blank;
  1557. IF InAField AND (line[indentation] # blank) THEN
  1558. (*We do the following to prevent the color change associated
  1559. with the field from beginning until _after_ the replaced
  1560. space.*)
  1561. INC( indentation );
  1562. INC(BlanksInARow);
  1563. IF ((BlanksInARow<3) AND (NOT firstcol)) OR HaveColor() THEN
  1564. StrEdit.Append(ImageRec.text, blank);
  1565. END;
  1566. END;
  1567. ELSE
  1568. M2Strings.Delete(line, indentation - 1, 1);
  1569. DEC( LineLngth );
  1570. END;
  1571. BlanksInARow := 0;
  1572. ColorChange := TRUE;
  1573. ELSIF WhichColor <= HIGH(ColorKeys) THEN
  1574. IF ColorStack^.Ccode = ColorKeys[ WhichColor] THEN
  1575. IF NOT DeleteColor() THEN
  1576. RETURN FALSE;
  1577. END;
  1578. ELSE
  1579. AddColor( ColorKeys[WhichColor], KeyFors[WhichColor],
  1580. KeyBacks[WhichColor], KeyAtrbs[WhichColor]);
  1581. END;
  1582. M2Strings.Delete(line, indentation - 1, 1);
  1583. DEC( LineLngth );
  1584. BlanksInARow := 0;
  1585. ColorChange := TRUE;
  1586. ELSIF line[indentation - 1]=blank THEN
  1587. INC(indentation);
  1588. INC(BlanksInARow);
  1589. IF ((BlanksInARow<3) AND (NOT firstcol)) OR HaveColor() THEN
  1590. StrEdit.Append(ImageRec.text, blank);
  1591. END;
  1592. ELSE
  1593. StrEdit.Append(ImageRec.text, line[indentation - 1]);
  1594. INC(indentation);
  1595. BlanksInARow := 0;
  1596. END;
  1597. END;
  1598. IF InAField THEN
  1599. RETURN ReportErr( FMErr );
  1600. END;
  1601. AddRecord( ImageRec);
  1602. RETURN TRUE;
  1603. END AddToOutList;
  1604. PROCEDURE DoDisplayArea();
  1605. VAR
  1606. TypeCode: CARDINAL;
  1607. BEGIN
  1608. LineCount := 0;
  1609. FieldCount := 0;
  1610. WHILE (CurrentLine < GenLists.ListLength( InListGlobal)) DO
  1611. INC( CurrentLine);
  1612. GenLists.GetElmt( InListGlobal, CurrentLine, Parser.TheLine, TypeCode);
  1613. (*read next line*)
  1614. StrEdit.ReplaceTabs( Parser.TheLine, 8 );
  1615. StrEdit.DeleteChar( FormFeed, Parser.TheLine );
  1616. IF PosUtils.Present(Parser.StartComment, Parser.TheLine) THEN
  1617. WHILE (NOT PosUtils.Present(Parser.EndComment, Parser.TheLine)) AND
  1618. (CurrentLine < GenLists.ListLength( InListGlobal)) DO
  1619. INC( CurrentLine);
  1620. GenLists.GetElmt( InListGlobal, CurrentLine,
  1621. Parser.TheLine, TypeCode);
  1622. (*read next line*)
  1623. StrEdit.ReplaceTabs( Parser.TheLine, 8 );
  1624. (*lets you put comments in a frame file*)
  1625. END;
  1626. ELSE
  1627. INC( LineCount);
  1628. IF NOT AddToOutList( Parser.TheLine) THEN
  1629. RETURN;
  1630. END;
  1631. END;
  1632. END;
  1633. CheckFieldNumber();
  1634. END DoDisplayArea;
  1635. PROCEDURE InsertFrameLinks( VAR LinkedFrames: GenLists.GenList);
  1636. BEGIN
  1637. IF (FrameAbove[0] # 0C)
  1638. OR (FrameBelow[0] # 0C)
  1639. OR (FrameRight[0] # 0C)
  1640. OR (FrameLeft[0] # 0C) THEN
  1641. GenLists.NewList( LinkedFrames );
  1642. GenLists.ListInsert( FrameAbove, GenLists.StrCode, LinkedFrames,
  1643. AfterLastElmt);
  1644. GenLists.ListInsert( FrameBelow, GenLists.StrCode, LinkedFrames,
  1645. AfterLastElmt);
  1646. GenLists.ListInsert( FrameLeft, GenLists.StrCode, LinkedFrames,
  1647. AfterLastElmt);
  1648. GenLists.ListInsert( FrameRight, GenLists.StrCode, LinkedFrames,
  1649. AfterLastElmt);
  1650. END;
  1651. END InsertFrameLinks;
  1652. PROCEDURE MakeOutList( VAR OutList: GenLists.GenList);
  1653. BEGIN
  1654. SetToDefaultColors( FrameRec );
  1655. GenLists.NewList( OutList);
  1656. GenLists.ListInsert( HelpFrame, GenLists.StrCode, OutList,
  1657. AfterLastElmt);
  1658. GenLists.ListInsert( ParentFrame, GenLists.StrCode,
  1659. OutList, AfterLastElmt);
  1660. GenLists.ListInsert( NormalNextFrame, GenLists.StrCode,
  1661. OutList, AfterLastElmt);
  1662. GenLists.ListInsert( FrameRec, RecType, OutList,
  1663. AfterLastElmt);
  1664. GenLists.ListInsert( DataList, GenLists.ListCode, OutList,
  1665. AfterLastElmt);
  1666. GenLists.ListInsert( PromptList, GenLists.ListCode,
  1667. OutList, AfterLastElmt);
  1668. GenLists.ListInsert( HelpList, GenLists.ListCode, OutList,
  1669. AfterLastElmt);
  1670. GenLists.ListInsert( EdList, GenLists.ListCode, OutList,
  1671. AfterLastElmt);
  1672. GenLists.ListInsert( FieldList, GenLists.ListCode, OutList,
  1673. AfterLastElmt);
  1674. GenLists.ListInsert( ImageList, GenLists.ListCode, OutList,
  1675. AfterLastElmt);
  1676. InsertFrameLinks( LinkedFrames );
  1677. GenLists.ListInsert( LinkedFrames, GenLists.ListCode, OutList,
  1678. AfterLastElmt);
  1679. END MakeOutList;
  1680. PROCEDURE CompileFrame( VAR InList, OutList: GenLists.GenList; VAR
  1681. FrameName: ScrnTypes.AFrameName; VAR ErrStr: ARRAY OF CHAR; VAR
  1682. BadLine: CARDINAL);
  1683. (* compiles a single frame *)
  1684. VAR
  1685. DataSize, TotalElems, TotalSize: LONGINT;
  1686. TotalSublists: CARDINAL;
  1687. BEGIN
  1688. DataSize := GenLists.ListSize( InList, TotalElems,
  1689. TotalSublists, TotalSize );
  1690. (*Check memory here because it's too hard to get out if we
  1691. run out below. Figure we need about as much as the
  1692. InList occupies.*)
  1693. IF (TotalSize > NumTypes.L65535) OR
  1694. (NOT VStorage.IsAvailable(Numbers.C(TotalSize))) THEN
  1695. ErrorManager.WARN( InsuffMem );
  1696. RETURN;
  1697. END;
  1698. InitOutLists();
  1699. (* initialize the output genlists *)
  1700. StrEdit.SetLength( ErrStrGlobal, 0);
  1701. (* init the error string & line # *)
  1702. BadLineGlobal := 0;
  1703. InListGlobal := InList;
  1704. StrEdit.SetLength( Parser.TheLine, 0);
  1705. (* init the global line and index *)
  1706. CurrentLine := 0;
  1707. CurrentIndex := 1;
  1708. IF GenLists.ListLength( InList) > 0 THEN
  1709. IF DoCommandArea( FrameName) THEN
  1710. DoDisplayArea();
  1711. END;
  1712. END;
  1713. MakeOutList( OutList);
  1714. StrEdit.AssignStr( ErrStrGlobal, ErrStr);
  1715. BadLine := BadLineGlobal;
  1716. END CompileFrame;
  1717. PROCEDURE InitColors();
  1718. BEGIN
  1719. StrEdit.SetLength( ColorKeys, 4 );
  1720. ColorKeys[0] := 367C; (* Flash *)
  1721. ColorKeys[1] := 27C; (* UnderScored *)
  1722. ColorKeys[2] := 341C; (* Bold *)
  1723. ColorKeys[3] := 352C; (* Reversed *)
  1724. KeyFors[0] := MsColors.lightgrey;
  1725. KeyFors[1] := MsColors.blue;
  1726. KeyFors[2] := MsColors.brightwhite;
  1727. KeyFors[3] := MsColors.black;
  1728. KeyBacks[0] := MsColors.darkgrey;
  1729. KeyBacks[1] := MsColors.black;
  1730. KeyBacks[2] := MsColors.black;
  1731. KeyBacks[3] := MsColors.lightgrey;
  1732. KeyAtrbs[0] := MsColors.blinking;
  1733. KeyAtrbs[1] := MsColors.underscored;
  1734. KeyAtrbs[2] := MsColors.bold;
  1735. KeyAtrbs[3] := MsColors.ReverseVideo;
  1736. END InitColors;
  1737. PROCEDURE Init();
  1738. BEGIN
  1739. IF Initialized THEN
  1740. RETURN;
  1741. ELSE
  1742. Initialized := TRUE;
  1743. END;
  1744. (*EntryDiag:
  1745. Diagnostics.Init();
  1746. :EntryDiag*)
  1747. ByteFiddler.Init();
  1748. ErrorManager.Init();
  1749. FieldTypes.Init();
  1750. GenLists.Init();
  1751. LowLevel.Init();
  1752. M2Strings.Init();
  1753. MsColors.Init();
  1754. NdxTypes.Init();
  1755. Numbers.Init();
  1756. NumTypes.Init();
  1757. Parser.Init();
  1758. PosUtils.Init();
  1759. ScrnTypes.Init();
  1760. ScrnUtl1.Init();
  1761. StrConv.Init();
  1762. StrCnv1.Init();
  1763. StrEdit.Init();
  1764. VStorage.Init();
  1765. VWindows.Init();
  1766. (*EntryDiag:
  1767. Diagnostics.diagS( 'Entering MakeFrame', '' );
  1768. :EntryDiag*)
  1769. (* First we initialize all the normal screen colors. Just
  1770. change these assignments if your taste in colors differs
  1771. from ours. *)
  1772. DefaultFore := MsColors.lightgrey;
  1773. DefaultBack := MsColors.blue;
  1774. DefaultAtrb := MsColors.plain;
  1775. DefaultBordatrb := MsColors.plain;
  1776. DefaultBordfor := MsColors.lightcyan;
  1777. DefaultBordbak := MsColors.blue;
  1778. (* Border colors *)
  1779. DefaultSelatrb := MsColors.bold;
  1780. DefaultSelfor := MsColors.lightmagenta;
  1781. DefaultSelbak := MsColors.blue;
  1782. (* Selected text *)
  1783. DefaultPbatrb := MsColors.ReverseVideo;
  1784. DefaultPbfor := MsColors.black;
  1785. DefaultPbbak := MsColors.red;
  1786. (* Pointer Bar Colors *)
  1787. DefaultMsgatrb := MsColors.plain;
  1788. DefaultMsgfor := MsColors.black;
  1789. DefaultMsgbak := MsColors.lightgrey;
  1790. (* Message Box Colors *)
  1791. DefaultPromatrb := MsColors.ReverseVideo;
  1792. DefaultPromfor := MsColors.black;
  1793. DefaultPrombak := MsColors.cyan;
  1794. (* Prompt Line Colors *)
  1795. ColorStack := SYSTEM.ADR(ColorBase);
  1796. (* ColorBase is a record of the type to which ColorStack is
  1797. supposed to point. *)
  1798. ColorStack^.Ccode := blank;
  1799. ColorStack^.forec := DefaultFore;
  1800. ColorStack^.backc := DefaultBack;
  1801. ColorStack^.atrbc := DefaultAtrb;
  1802. ColorStack^.nxt := NIL;
  1803. ColorStack^.prv := NIL;
  1804. InitColors();
  1805. FieldMark := '#';
  1806. ReplacingFieldMarks := FALSE;
  1807. StrEdit.AssignStr( '====================', CommandBeginStr);
  1808. StrEdit.AssignStr( '--------------------', CommandEndStr);
  1809. (*EntryDiag:
  1810. Diagnostics.diagS( 'Exiting MakeFrame', '' );
  1811. :EntryDiag*)
  1812. END Init;
  1813. BEGIN
  1814. Initialized := FALSE;
  1815. Init();
  1816. END MakeFrame.