Shell.mod 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  1. MODULE Shell ;
  2. (* TP3 main-menu shell. Draws the Turbo Pascal 3.0 screen with ANSI
  3. escapes and dispatches on the same command letters as the original
  4. (TPSRC4 kmenu / kcmdtab). Editor, compiler and interpreter are
  5. placeholders for now; the shell logic (files, directory, options,
  6. save/load with .BAK) mirrors the original closely. *)
  7. FROM Term IMPORT
  8. Open, Close, ClrScr, GotoXY, PutCh, PutStr, PutCard, PutLongCard,
  9. ScrnWide, Marked, Normal, GetCh, Beep ;
  10. FROM Posix IMPORT
  11. read, write, open, close, unlink, rename,
  12. getcwd, chdir, opendir, readdir, closedir, statvfs,
  13. Dir, dirent, statvfsbuf ;
  14. FROM SYSTEM IMPORT ADR, ADDRESS, BYTE ;
  15. CONST
  16. TextLimit = 62903 ;
  17. O_RDONLY = 0 ; (* linux *)
  18. VAR
  19. drive : CHAR ;
  20. workName : ARRAY [0..255] OF CHAR ;
  21. mainName : ARRAY [0..255] OF CHAR ;
  22. txt : ARRAY [0..TextLimit] OF BYTE ;
  23. txtLen : CARDINAL ;
  24. changed : BOOLEAN ;
  25. codeDest : CARDINAL ; (* 0=Memory, 1=COM, 2=CHN *)
  26. minCode, minData, minStack, maxStack : CARDINAL ;
  27. paramLine : ARRAY [0..255] OF CHAR ;
  28. (* ------------------------------------------------------------------ *)
  29. (* string helpers *)
  30. (* ------------------------------------------------------------------ *)
  31. PROCEDURE StrLen (VAR s : ARRAY OF CHAR) : CARDINAL ;
  32. VAR i : CARDINAL ;
  33. BEGIN
  34. i := 0 ;
  35. WHILE (i <= HIGH (s)) AND (s [i] # 0C) DO
  36. INC (i)
  37. END ;
  38. RETURN i
  39. END StrLen ;
  40. PROCEDURE StrClear (VAR s : ARRAY OF CHAR) ;
  41. BEGIN
  42. s [0] := 0C
  43. END StrClear ;
  44. PROCEDURE StrCopy (VAR dst : ARRAY OF CHAR ; src : ARRAY OF CHAR) ;
  45. VAR i : CARDINAL ;
  46. BEGIN
  47. i := 0 ;
  48. LOOP
  49. IF i > HIGH (dst) THEN
  50. dst [HIGH (dst)] := 0C ;
  51. EXIT
  52. END ;
  53. IF i > HIGH (src) THEN
  54. dst [i] := 0C ;
  55. EXIT
  56. END ;
  57. IF src [i] = 0C THEN
  58. dst [i] := 0C ;
  59. EXIT
  60. END ;
  61. dst [i] := src [i] ;
  62. INC (i)
  63. END
  64. END StrCopy ;
  65. PROCEDURE StrAppend (VAR dst : ARRAY OF CHAR ; suffix : ARRAY OF CHAR) ;
  66. VAR i, j : CARDINAL ;
  67. BEGIN
  68. i := StrLen (dst) ;
  69. j := 0 ;
  70. LOOP
  71. IF i > HIGH (dst) THEN
  72. EXIT
  73. END ;
  74. IF j > HIGH (suffix) THEN
  75. dst [i] := 0C ;
  76. EXIT
  77. END ;
  78. IF suffix [j] = 0C THEN
  79. dst [i] := 0C ;
  80. EXIT
  81. END ;
  82. dst [i] := suffix [j] ;
  83. INC (i) ;
  84. INC (j)
  85. END
  86. END StrAppend ;
  87. PROCEDURE StrEq (VAR a, b : ARRAY OF CHAR) : BOOLEAN ;
  88. VAR i : CARDINAL ;
  89. BEGIN
  90. i := 0 ;
  91. LOOP
  92. IF (i > HIGH (a)) OR (i > HIGH (b)) THEN
  93. RETURN FALSE
  94. END ;
  95. IF (a [i] = 0C) AND (b [i] = 0C) THEN
  96. RETURN TRUE
  97. END ;
  98. IF a [i] # b [i] THEN
  99. RETURN FALSE
  100. END ;
  101. INC (i)
  102. END ;
  103. RETURN FALSE
  104. END StrEq ;
  105. PROCEDURE Upper (ch : CHAR) : CHAR ;
  106. BEGIN
  107. IF (ch >= "a") AND (ch <= "z") THEN
  108. RETURN CHR (ORD (ch) - (ORD ("a") - ORD ("A")))
  109. END ;
  110. RETURN ch
  111. END Upper ;
  112. PROCEDURE CrLf ;
  113. BEGIN
  114. PutCh (CHR (13)) ;
  115. PutCh (CHR (10))
  116. END CrLf ;
  117. PROCEDURE GetCwd (VAR buf : ARRAY OF CHAR) ;
  118. VAR i : CARDINAL ;
  119. BEGIN
  120. IF getcwd (ADR (buf), 4096) = NIL THEN
  121. buf [0] := 0C
  122. END
  123. END GetCwd ;
  124. (* ------------------------------------------------------------------ *)
  125. (* marks one command letter then prints the rest of the label *)
  126. (* ------------------------------------------------------------------ *)
  127. PROCEDURE Key (letter, rest : ARRAY OF CHAR) ;
  128. BEGIN
  129. Marked ;
  130. PutCh (letter [0]) ;
  131. Normal ;
  132. PutStr (rest)
  133. END Key ;
  134. (* ------------------------------------------------------------------ *)
  135. (* input line editing (no echo from termios): CR or LF ends the line, *)
  136. (* backspace deletes the last char, the result is stored 0C-terminated*)
  137. (* ------------------------------------------------------------------ *)
  138. PROCEDURE ReadLine (VAR s : ARRAY OF CHAR) : CARDINAL ;
  139. VAR len : CARDINAL ;
  140. ch : CHAR ;
  141. BEGIN
  142. StrClear (s) ;
  143. len := 0 ;
  144. LOOP
  145. GetCh (ch) ;
  146. IF (ch = CHR (13)) OR (ch = CHR (10)) THEN
  147. PutCh (CHR (13)) ;
  148. PutCh (CHR (10)) ;
  149. EXIT
  150. ELSIF (ch = CHR (8)) OR (ch = CHR (127)) THEN
  151. IF len > 0 THEN
  152. DEC (len) ;
  153. PutStr (" ") (* backspace over the char *)
  154. END
  155. ELSIF ch = CHR (27) THEN
  156. (* ESC: cancel the current edit *)
  157. EXIT
  158. ELSIF (ch >= " ") AND (ch <= "~") AND (len < HIGH (s)) THEN
  159. s [len] := ch ;
  160. INC (len) ;
  161. PutCh (ch)
  162. END
  163. END ;
  164. s [len] := 0C ;
  165. RETURN len
  166. END ReadLine ;
  167. PROCEDURE Pause ;
  168. VAR ch : CHAR ;
  169. BEGIN
  170. Beep ;
  171. GetCh (ch)
  172. END Pause ;
  173. PROCEDURE WaitEsc ;
  174. VAR ch : CHAR ;
  175. BEGIN
  176. LOOP
  177. GetCh (ch) ;
  178. IF (ch = CHR (27)) OR (ch = "q") OR (ch = "Q") THEN
  179. EXIT
  180. END
  181. END
  182. END WaitEsc ;
  183. (* return true if the user confirms with Y / y *)
  184. PROCEDURE Confirm (prompt : ARRAY OF CHAR) : BOOLEAN ;
  185. VAR ch : CHAR ;
  186. BEGIN
  187. PutStr (prompt) ;
  188. GetCh (ch) ;
  189. IF (ch = "y") OR (ch = "Y") THEN
  190. CrLf ;
  191. RETURN TRUE
  192. END ;
  193. CrLf ;
  194. RETURN FALSE
  195. END Confirm ;
  196. (* ------------------------------------------------------------------ *)
  197. (* file name handling *)
  198. (* ------------------------------------------------------------------ *)
  199. (* Does the name contain a '.' ? *)
  200. PROCEDURE HasExt (VAR s : ARRAY OF CHAR) : BOOLEAN ;
  201. VAR i : CARDINAL ;
  202. BEGIN
  203. i := 0 ;
  204. WHILE (i <= HIGH (s)) AND (s [i] # 0C) DO
  205. IF s [i] = "." THEN
  206. RETURN TRUE
  207. END ;
  208. INC (i)
  209. END ;
  210. RETURN FALSE
  211. END HasExt ;
  212. (* replaces the current work file, appending .PAS when needed *)
  213. PROCEDURE SetWorkName (VAR s : ARRAY OF CHAR) ;
  214. BEGIN
  215. StrCopy (workName, s) ;
  216. IF NOT HasExt (workName) THEN
  217. StrAppend (workName, ".PAS")
  218. END
  219. END SetWorkName ;
  220. (* ------------------------------------------------------------------ *)
  221. (* buffered save of the work file: .BAK = old version, then ^Z *)
  222. (* ------------------------------------------------------------------ *)
  223. PROCEDURE SaveWorkFile ;
  224. VAR fd : INTEGER ;
  225. path : ARRAY [0..511] OF CHAR ;
  226. w : LONGINT ;
  227. i : CARDINAL ;
  228. msg : ARRAY [0..255] OF CHAR ;
  229. b : BYTE ;
  230. BEGIN
  231. IF StrLen (workName) = 0 THEN
  232. PutStr (" ...work file not set") ;
  233. CrLf ;
  234. Pause ;
  235. RETURN
  236. END ;
  237. StrClear (msg) ;
  238. StrAppend (msg, "Saving A:") ;
  239. StrAppend (msg, workName) ;
  240. PutStr (msg) ;
  241. StrClear (path) ;
  242. StrAppend (path, workName) ;
  243. StrAppend (path, ".BAK") ;
  244. w := unlink (ADR (path)) ; (* drop old backup *)
  245. StrClear (path) ;
  246. StrAppend (path, workName) ;
  247. StrAppend (path, ".BAK") ;
  248. StrClear (msg) ;
  249. StrAppend (msg, workName) ;
  250. w := rename (ADR (msg), ADR (path)) ; (* old version -> .BAK *)
  251. StrClear (path) ;
  252. StrAppend (path, workName) ;
  253. fd := open (ADR (path), 1 + 512 + 64, 420) ; (* O_WRONLY|O_TRUNC|O_CREAT, 0644 *)
  254. IF fd < 0 THEN
  255. CrLf ;
  256. PutStr (" ...cannot create file") ;
  257. Pause ;
  258. RETURN
  259. END ;
  260. i := 0 ;
  261. WHILE i < txtLen DO
  262. w := write (fd, ADR (txt [i]), 1) ;
  263. INC (i)
  264. END ;
  265. b := CHR (26) ; (* EOF marker ^Z, TP3 style *)
  266. w := write (fd, ADR (b), 1) ;
  267. w := close (fd) ;
  268. changed := FALSE ;
  269. CrLf
  270. END SaveWorkFile ;
  271. (* ------------------------------------------------------------------ *)
  272. (* load a file into the text buffer; stop at ^Z or TextLimit *)
  273. (* ------------------------------------------------------------------ *)
  274. PROCEDURE LoadWorkFile ;
  275. VAR fd : INTEGER ;
  276. path : ARRAY [0..511] OF CHAR ;
  277. n, i : CARDINAL ;
  278. k : LONGINT ;
  279. b : BYTE ;
  280. tooBig : BOOLEAN ;
  281. BEGIN
  282. StrClear (path) ;
  283. StrAppend (path, workName) ;
  284. fd := open (ADR (path), O_RDONLY, 0) ;
  285. IF fd < 0 THEN
  286. PutStr ("New File") ;
  287. CrLf ;
  288. txtLen := 0 ;
  289. changed := FALSE ;
  290. Pause ;
  291. RETURN
  292. END ;
  293. tooBig := FALSE ;
  294. txtLen := 0 ;
  295. LOOP
  296. IF txtLen >= TextLimit THEN
  297. tooBig := TRUE ;
  298. EXIT
  299. END ;
  300. k := read (fd, ADR (b), 1) ;
  301. IF k # 1 THEN
  302. EXIT
  303. END ;
  304. IF b = CHR (26) THEN
  305. EXIT
  306. END ;
  307. txt [txtLen] := b ;
  308. INC (txtLen)
  309. END ;
  310. k := close (fd) ;
  311. IF tooBig THEN
  312. PutStr ("File too big") ;
  313. CrLf
  314. END ;
  315. changed := FALSE ;
  316. Pause
  317. END LoadWorkFile ;
  318. (* ------------------------------------------------------------------ *)
  319. (* directory listing (kdir) *)
  320. (* ------------------------------------------------------------------ *)
  321. PROCEDURE MatchMask (VAR m, n : ARRAY OF CHAR) : BOOLEAN ;
  322. VAR mi, ni, saveMi, saveNi : CARDINAL ;
  323. isAll : BOOLEAN ;
  324. BEGIN
  325. (* DOS-style: "*.*" and "*" mean "everything" *)
  326. isAll := TRUE ;
  327. mi := 0 ;
  328. WHILE (mi <= HIGH (m)) AND (m [mi] # 0C) DO
  329. IF NOT ((m [mi] = "*") OR (m [mi] = ".")) THEN
  330. isAll := FALSE
  331. END ;
  332. INC (mi)
  333. END ;
  334. IF isAll THEN
  335. RETURN TRUE
  336. END ;
  337. mi := 0 ;
  338. ni := 0 ;
  339. saveMi := 0 ;
  340. saveNi := 0 ;
  341. LOOP
  342. (* mask exhausted *)
  343. IF (mi <= HIGH (m)) AND (m [mi] = "*") THEN
  344. saveMi := mi ;
  345. WHILE (mi <= HIGH (m)) AND (m [mi] = "*") DO
  346. INC (mi)
  347. END ;
  348. IF mi > HIGH (m) THEN
  349. RETURN TRUE
  350. END ;
  351. saveNi := ni
  352. ELSIF (mi > HIGH (m)) OR (m [mi] = 0C) THEN
  353. RETURN (ni <= HIGH (n)) AND (n [ni] = 0C)
  354. ELSIF (ni <= HIGH (n)) AND (n [ni] # 0C) AND
  355. (Upper (m [mi]) = Upper (n [ni])) THEN
  356. INC (mi) ;
  357. INC (ni)
  358. ELSIF saveMi > 0 THEN
  359. INC (saveNi) ;
  360. IF saveNi > HIGH (n) THEN
  361. RETURN FALSE
  362. END ;
  363. ni := saveNi ;
  364. mi := saveMi + 1
  365. ELSIF (ni > HIGH (n)) OR (n [ni] = 0C) THEN
  366. RETURN FALSE
  367. ELSE
  368. RETURN FALSE
  369. END
  370. END ;
  371. RETURN FALSE
  372. END MatchMask ;
  373. PROCEDURE DirCmd ;
  374. VAR mask : ARRAY [0..255] OF CHAR ;
  375. d : Dir ;
  376. p : POINTER TO dirent ;
  377. count : CARDINAL ;
  378. freeK : LONGCARD ;
  379. sv : statvfsbuf ;
  380. i : CARDINAL ;
  381. w : INTEGER ;
  382. BEGIN
  383. PutStr ("Dir mask: ") ;
  384. IF ReadLine (mask) = 0 THEN
  385. StrCopy (mask, "*.*")
  386. END ;
  387. CrLf ;
  388. d := opendir (ADR (".")) ;
  389. IF d = NIL THEN
  390. PutStr ("No files") ;
  391. CrLf ;
  392. Pause ;
  393. RETURN
  394. END ;
  395. count := 0 ;
  396. LOOP
  397. p := readdir (d) ;
  398. IF p = NIL THEN
  399. EXIT
  400. END ;
  401. IF (p^.d_name [0] # ".") AND
  402. (MatchMask (mask, p^.d_name)) THEN
  403. INC (count) ;
  404. PutStr (p^.d_name) ;
  405. i := 1 + (12 - StrLen (p^.d_name) MOD 12) ;
  406. IF i > 12 THEN
  407. i := 12
  408. END ;
  409. ScrnWide (i)
  410. END
  411. END ;
  412. w := closedir (d) ;
  413. CrLf ;
  414. IF count = 0 THEN
  415. PutStr ("No files") ;
  416. CrLf
  417. END ;
  418. IF statvfs (ADR ("."), ADR (sv)) = 0 THEN
  419. freeK := (sv.f_bavail * sv.f_frsize) DIV 1024 ;
  420. PutLongCard (freeK) ;
  421. PutStr ("k bytes free") ;
  422. CrLf
  423. END ;
  424. Pause
  425. END DirCmd ;
  426. (* ------------------------------------------------------------------ *)
  427. (* main menu *)
  428. (* ------------------------------------------------------------------ *)
  429. PROCEDURE DrawMenu ;
  430. VAR cwd : ARRAY [0..4095] OF CHAR ;
  431. freeB : CARDINAL ;
  432. i : CARDINAL ;
  433. BEGIN
  434. ClrScr ;
  435. GotoXY (1, 1) ;
  436. Key ("L", "ogged drive: ") ;
  437. PutCh (drive) ;
  438. GetCwd (cwd) ;
  439. GotoXY (2, 1) ;
  440. Key ("A", "ctive directory: ") ;
  441. PutStr (cwd) ;
  442. GotoXY (4, 1) ;
  443. Key ("W", "ork file: A:") ;
  444. PutStr (workName) ;
  445. GotoXY (5, 1) ;
  446. Key ("M", "ain file: A:") ;
  447. PutStr (mainName) ;
  448. GotoXY (7, 1) ;
  449. Key ("E", "dit ") ;
  450. Key ("C", "ompile ") ;
  451. Key ("R", "un ") ;
  452. Key ("S", "ave") ;
  453. GotoXY (9, 1) ;
  454. Key ("D", "ir ") ;
  455. Key ("Q", "uit compiler ") ;
  456. Key ("O", "ptions") ;
  457. GotoXY (11, 1) ;
  458. PutStr ("Text: ") ;
  459. PutCard (txtLen) ;
  460. PutStr (" bytes") ;
  461. freeB := TextLimit - txtLen ;
  462. GotoXY (12, 1) ;
  463. PutStr ("Free: ") ;
  464. PutCard (freeB) ;
  465. PutStr (" bytes") ;
  466. GotoXY (14, 1) ;
  467. Marked ;
  468. PutCh (">") ;
  469. Normal
  470. END DrawMenu ;
  471. (* ------------------------------------------------------------------ *)
  472. (* command handlers *)
  473. (* ------------------------------------------------------------------ *)
  474. PROCEDURE CmdLogDrive ;
  475. VAR nm : ARRAY [0..255] OF CHAR ;
  476. ln : CARDINAL ;
  477. BEGIN
  478. ClrScr ;
  479. GotoXY (1, 1) ;
  480. PutStr ("New drive: ") ;
  481. ln := ReadLine (nm) ;
  482. IF ln = 1 THEN
  483. drive := Upper (nm [0]) ;
  484. IF (drive < "A") OR (drive > "P") THEN
  485. drive := "A"
  486. END
  487. ELSIF ln > 1 THEN
  488. (* treat as a directory instead (linux has no real drives) *)
  489. IF chdir (ADR (nm)) # 0 THEN
  490. PutStr ("File not found") ;
  491. CrLf ;
  492. Pause
  493. END
  494. END
  495. END CmdLogDrive ;
  496. PROCEDURE CmdActDir ;
  497. VAR nm : ARRAY [0..255] OF CHAR ;
  498. BEGIN
  499. ClrScr ;
  500. GotoXY (1, 1) ;
  501. PutStr ("New directory: ") ;
  502. IF ReadLine (nm) > 0 THEN
  503. IF chdir (ADR (nm)) # 0 THEN
  504. PutStr ("File not found") ;
  505. CrLf ;
  506. Pause
  507. END
  508. END
  509. END CmdActDir ;
  510. PROCEDURE CmdWorkFile ;
  511. VAR nm : ARRAY [0..255] OF CHAR ;
  512. txtTitle : ARRAY [0..511] OF CHAR ;
  513. BEGIN
  514. ClrScr ;
  515. GotoXY (1, 1) ;
  516. PutStr ("Work file name: ") ;
  517. IF ReadLine (nm) > 0 THEN
  518. IF changed THEN
  519. CrLf ;
  520. PutStr (" ") ;
  521. IF Confirm ("Save current work file now (Y/N) ?") THEN
  522. SaveWorkFile
  523. END
  524. END ;
  525. ClrScr ;
  526. GotoXY (1, 1) ;
  527. SetWorkName (nm) ;
  528. StrClear (txtTitle) ;
  529. StrAppend (txtTitle, "Loading A:") ;
  530. StrAppend (txtTitle, workName) ;
  531. PutStr (txtTitle) ;
  532. CrLf ;
  533. LoadWorkFile
  534. END
  535. END CmdWorkFile ;
  536. PROCEDURE CmdMainFile ;
  537. VAR nm : ARRAY [0..255] OF CHAR ;
  538. BEGIN
  539. ClrScr ;
  540. GotoXY (1, 1) ;
  541. PutStr ("Main file name: ") ;
  542. IF ReadLine (nm) > 0 THEN
  543. StrCopy (mainName, nm) ;
  544. IF NOT HasExt (mainName) THEN
  545. StrAppend (mainName, ".PAS")
  546. END
  547. END
  548. END CmdMainFile ;
  549. PROCEDURE CmdCompile ;
  550. BEGIN
  551. ClrScr ;
  552. GotoXY (1, 1) ;
  553. PutStr ("Compiler under construction - press ESC") ;
  554. CrLf ;
  555. WaitEsc
  556. END CmdCompile ;
  557. PROCEDURE CmdRun ;
  558. BEGIN
  559. ClrScr ;
  560. GotoXY (1, 1) ;
  561. PutStr ("Compiler / interpreter under construction - press ESC") ;
  562. CrLf ;
  563. WaitEsc
  564. END CmdRun ;
  565. PROCEDURE CmdEditor ;
  566. BEGIN
  567. ClrScr ;
  568. GotoXY (1, 1) ;
  569. PutStr ("Editor under construction - press ESC") ;
  570. CrLf ;
  571. WaitEsc
  572. END CmdEditor ;
  573. (* ------------------------------------------------------------------ *)
  574. (* TP3 "Options" submenu (optmenu) *)
  575. (* ------------------------------------------------------------------ *)
  576. PROCEDURE PutHex (n : CARDINAL) ;
  577. VAR dig : ARRAY [0..7] OF CHAR ;
  578. i, d : CARDINAL ;
  579. BEGIN
  580. i := 0 ;
  581. LOOP
  582. d := n MOD 16 ;
  583. IF d < 10 THEN
  584. dig [i] := CHR (ORD ("0") + d)
  585. ELSE
  586. dig [i] := CHR (ORD ("A") + d - 10)
  587. END ;
  588. n := n DIV 16 ;
  589. INC (i) ;
  590. IF (n = 0) OR (i = 8) THEN
  591. EXIT
  592. END
  593. END ;
  594. WHILE i > 0 DO
  595. DEC (i) ;
  596. PutCh (dig [i])
  597. END
  598. END PutHex ;
  599. PROCEDURE OptionsMenu ;
  600. VAR ch : CHAR ;
  601. s : ARRAY [0..255] OF CHAR ;
  602. done : BOOLEAN ;
  603. BEGIN
  604. done := FALSE ;
  605. REPEAT
  606. ClrScr ;
  607. GotoXY (1, 1) ;
  608. Marked ; PutCh ("M") ; Normal ;
  609. PutStr ("emory ") ;
  610. Marked ; PutCh ("C") ; Normal ;
  611. PutStr ("OM ") ;
  612. Marked ; PutCh ("H") ; Normal ;
  613. PutStr ("CHN") ;
  614. CrLf ;
  615. PutStr (" ") ;
  616. IF codeDest = 1 THEN
  617. PutStr ("Compile -> COM")
  618. ELSIF codeDest = 2 THEN
  619. PutStr ("Compile -> CHN")
  620. ELSE
  621. PutStr ("Compile -> Memory")
  622. END ;
  623. CrLf ;
  624. PutStr ("Text: ") ;
  625. PutCard (txtLen) ;
  626. PutStr (" Code: ") ;
  627. PutHex (minCode) ;
  628. PutStr (" Data: ") ;
  629. PutHex (minData) ;
  630. PutStr (" Stack: ") ;
  631. PutHex (minStack) ;
  632. CrLf ;
  633. PutStr ("Command line Params: ") ;
  634. PutStr (paramLine) ;
  635. CrLf ;
  636. Marked ; PutCh ("F") ; Normal ;
  637. PutStr ("ind run-time error ") ;
  638. Marked ; PutCh ("Q") ; Normal ;
  639. PutStr ("uit") ;
  640. CrLf ;
  641. CrLf ;
  642. Marked ; PutCh (">") ; Normal ;
  643. GetCh (ch) ;
  644. ch := Upper (ch) ;
  645. CASE ch OF
  646. | "M" : codeDest := 0
  647. | "C" : codeDest := 1
  648. | "H" : codeDest := 2
  649. | "O" :
  650. ClrScr ; GotoXY (1,1) ;
  651. PutStr ("Min Code Segment (hex): ") ;
  652. IF ReadLine (s) > 0 THEN minCode := 0 END
  653. | "D" :
  654. ClrScr ; GotoXY (1,1) ;
  655. PutStr ("Min Data Segment (hex): ") ;
  656. IF ReadLine (s) > 0 THEN minData := 0 END
  657. | "I" :
  658. ClrScr ; GotoXY (1,1) ;
  659. PutStr ("Min Free Dyn Mem / Stack (hex): ") ;
  660. IF ReadLine (s) > 0 THEN minStack := 0 END
  661. | "A" :
  662. ClrScr ; GotoXY (1,1) ;
  663. PutStr ("Max Free Dyn Mem / Stack (hex): ") ;
  664. IF ReadLine (s) > 0 THEN maxStack := 0 END
  665. | "P" :
  666. ClrScr ; GotoXY (1,1) ;
  667. PutStr ("Command line Params: ") ;
  668. IF ReadLine (paramLine) > 0 THEN
  669. (* keep the parameter string *)
  670. END
  671. | "F" :
  672. ClrScr ; GotoXY (1,1) ;
  673. PutStr ("Find run-time error address (hex) : ") ;
  674. IF ReadLine (s) > 0 THEN
  675. PutStr ("Searching ... (not implemented)") ;
  676. CrLf ;
  677. Pause
  678. END
  679. | "Q" :
  680. done := TRUE
  681. ELSE
  682. (* ignore *)
  683. END
  684. UNTIL done
  685. END OptionsMenu ;
  686. (* ------------------------------------------------------------------ *)
  687. PROCEDURE terminal ;
  688. VAR ch : CHAR ;
  689. BEGIN
  690. Open ;
  691. drive := "A" ;
  692. codeDest := 0 ;
  693. minCode := 0 ; minData := 0 ; minStack := 0 ; maxStack := 0 ;
  694. StrClear (workName) ;
  695. StrClear (mainName) ;
  696. StrClear (paramLine) ;
  697. txtLen := 0 ;
  698. changed := FALSE ;
  699. LOOP
  700. DrawMenu ;
  701. GetCh (ch) ;
  702. ch := Upper (ch) ;
  703. CASE ch OF
  704. | "L" : CmdLogDrive
  705. | "A" : CmdActDir
  706. | "W" : CmdWorkFile
  707. | "M" : CmdMainFile
  708. | "E" : CmdEditor
  709. | "C" : CmdCompile
  710. | "R" : CmdRun
  711. | "S" :
  712. IF StrLen (workName) > 0 THEN
  713. SaveWorkFile ;
  714. Pause
  715. END
  716. | "D" : DirCmd
  717. | "O" : OptionsMenu
  718. | "Q" :
  719. IF changed THEN
  720. CrLf ;
  721. IF Confirm ("Work file not saved. Save (Y/N) ?") THEN
  722. SaveWorkFile
  723. END
  724. END ;
  725. Close ;
  726. HALT
  727. ELSE
  728. (* any other key: redraw the menu, like TP3 *)
  729. END
  730. END
  731. END terminal ;
  732. BEGIN
  733. terminal
  734. END Shell.