Shell.mod 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828
  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 Editor IMPORT Run ;
  15. FROM TextBuf IMPORT
  16. TextLimit, Clear, Length, CharAt, InsertCh ;
  17. FROM SYSTEM IMPORT ADR, ADDRESS, BYTE ;
  18. CONST
  19. O_RDONLY = 0 ; (* linux *)
  20. VAR
  21. drive : CHAR ;
  22. workName : ARRAY [0..255] OF CHAR ;
  23. mainName : ARRAY [0..255] OF CHAR ;
  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 < Length () DO
  262. IF CharAt (i) = CHR (13) THEN
  263. b := CHR (13) ;
  264. w := write (fd, ADR (b), 1) ;
  265. b := CHR (10) ;
  266. w := write (fd, ADR (b), 1)
  267. ELSE
  268. b := VAL (BYTE, ORD (CharAt (i))) ;
  269. w := write (fd, ADR (b), 1)
  270. END ;
  271. INC (i)
  272. END ;
  273. b := CHR (26) ; (* EOF marker ^Z, TP3 style *)
  274. w := write (fd, ADR (b), 1) ;
  275. w := close (fd) ;
  276. changed := FALSE ;
  277. CrLf
  278. END SaveWorkFile ;
  279. (* ------------------------------------------------------------------ *)
  280. (* load a file into the text buffer; stop at ^Z or TextLimit *)
  281. (* ------------------------------------------------------------------ *)
  282. PROCEDURE LoadWorkFile ;
  283. VAR fd : INTEGER ;
  284. path : ARRAY [0..511] OF CHAR ;
  285. k : LONGINT ;
  286. b : BYTE ;
  287. prevCR, tooBig : BOOLEAN ;
  288. BEGIN
  289. StrClear (path) ;
  290. StrAppend (path, workName) ;
  291. fd := open (ADR (path), O_RDONLY, 0) ;
  292. IF fd < 0 THEN
  293. PutStr ("New File") ;
  294. CrLf ;
  295. Clear ;
  296. changed := FALSE ;
  297. Pause ;
  298. RETURN
  299. END ;
  300. tooBig := FALSE ;
  301. prevCR := FALSE ;
  302. Clear ;
  303. LOOP
  304. IF Length () >= TextLimit THEN
  305. tooBig := TRUE ;
  306. EXIT
  307. END ;
  308. k := read (fd, ADR (b), 1) ;
  309. IF k # 1 THEN
  310. EXIT
  311. END ;
  312. IF b = CHR (26) THEN
  313. EXIT
  314. ELSIF b = CHR (10) THEN
  315. IF NOT prevCR THEN
  316. InsertCh (Length (), CHR (13)) (* lone LF -> CR *)
  317. END ;
  318. prevCR := FALSE
  319. ELSIF b = CHR (13) THEN
  320. InsertCh (Length (), CHR (13)) ;
  321. prevCR := TRUE
  322. ELSE
  323. InsertCh (Length (), CHR (ORD (b))) ;
  324. prevCR := FALSE
  325. END
  326. END ;
  327. k := close (fd) ;
  328. IF tooBig THEN
  329. PutStr ("File too big") ;
  330. CrLf
  331. END ;
  332. changed := FALSE ;
  333. Pause
  334. END LoadWorkFile ;
  335. (* ------------------------------------------------------------------ *)
  336. (* directory listing (kdir) *)
  337. (* ------------------------------------------------------------------ *)
  338. PROCEDURE MatchMask (VAR m, n : ARRAY OF CHAR) : BOOLEAN ;
  339. VAR mi, ni, saveMi, saveNi : CARDINAL ;
  340. isAll : BOOLEAN ;
  341. BEGIN
  342. (* DOS-style: "*.*" and "*" mean "everything" *)
  343. isAll := TRUE ;
  344. mi := 0 ;
  345. WHILE (mi <= HIGH (m)) AND (m [mi] # 0C) DO
  346. IF NOT ((m [mi] = "*") OR (m [mi] = ".")) THEN
  347. isAll := FALSE
  348. END ;
  349. INC (mi)
  350. END ;
  351. IF isAll THEN
  352. RETURN TRUE
  353. END ;
  354. mi := 0 ;
  355. ni := 0 ;
  356. saveMi := 0 ;
  357. saveNi := 0 ;
  358. LOOP
  359. (* mask exhausted *)
  360. IF (mi <= HIGH (m)) AND (m [mi] = "*") THEN
  361. saveMi := mi ;
  362. WHILE (mi <= HIGH (m)) AND (m [mi] = "*") DO
  363. INC (mi)
  364. END ;
  365. IF mi > HIGH (m) THEN
  366. RETURN TRUE
  367. END ;
  368. saveNi := ni
  369. ELSIF (mi > HIGH (m)) OR (m [mi] = 0C) THEN
  370. RETURN (ni <= HIGH (n)) AND (n [ni] = 0C)
  371. ELSIF (ni <= HIGH (n)) AND (n [ni] # 0C) AND
  372. (Upper (m [mi]) = Upper (n [ni])) THEN
  373. INC (mi) ;
  374. INC (ni)
  375. ELSIF saveMi > 0 THEN
  376. INC (saveNi) ;
  377. IF saveNi > HIGH (n) THEN
  378. RETURN FALSE
  379. END ;
  380. ni := saveNi ;
  381. mi := saveMi + 1
  382. ELSIF (ni > HIGH (n)) OR (n [ni] = 0C) THEN
  383. RETURN FALSE
  384. ELSE
  385. RETURN FALSE
  386. END
  387. END ;
  388. RETURN FALSE
  389. END MatchMask ;
  390. PROCEDURE DirCmd ;
  391. VAR mask : ARRAY [0..255] OF CHAR ;
  392. d : Dir ;
  393. p : POINTER TO dirent ;
  394. count : CARDINAL ;
  395. freeK : LONGCARD ;
  396. sv : statvfsbuf ;
  397. i : CARDINAL ;
  398. w : INTEGER ;
  399. BEGIN
  400. PutStr ("Dir mask: ") ;
  401. IF ReadLine (mask) = 0 THEN
  402. StrCopy (mask, "*.*")
  403. END ;
  404. CrLf ;
  405. d := opendir (ADR (".")) ;
  406. IF d = NIL THEN
  407. PutStr ("No files") ;
  408. CrLf ;
  409. Pause ;
  410. RETURN
  411. END ;
  412. count := 0 ;
  413. LOOP
  414. p := readdir (d) ;
  415. IF p = NIL THEN
  416. EXIT
  417. END ;
  418. IF (p^.d_name [0] # ".") AND
  419. (MatchMask (mask, p^.d_name)) THEN
  420. INC (count) ;
  421. PutStr (p^.d_name) ;
  422. i := 1 + (12 - StrLen (p^.d_name) MOD 12) ;
  423. IF i > 12 THEN
  424. i := 12
  425. END ;
  426. ScrnWide (i)
  427. END
  428. END ;
  429. w := closedir (d) ;
  430. CrLf ;
  431. IF count = 0 THEN
  432. PutStr ("No files") ;
  433. CrLf
  434. END ;
  435. IF statvfs (ADR ("."), ADR (sv)) = 0 THEN
  436. freeK := (sv.f_bavail * sv.f_frsize) DIV 1024 ;
  437. PutLongCard (freeK) ;
  438. PutStr ("k bytes free") ;
  439. CrLf
  440. END ;
  441. Pause
  442. END DirCmd ;
  443. (* ------------------------------------------------------------------ *)
  444. (* main menu *)
  445. (* ------------------------------------------------------------------ *)
  446. PROCEDURE DrawMenu ;
  447. VAR cwd : ARRAY [0..4095] OF CHAR ;
  448. freeB : CARDINAL ;
  449. i : CARDINAL ;
  450. BEGIN
  451. ClrScr ;
  452. GotoXY (1, 1) ;
  453. Key ("L", "ogged drive: ") ;
  454. PutCh (drive) ;
  455. GetCwd (cwd) ;
  456. GotoXY (2, 1) ;
  457. Key ("A", "ctive directory: ") ;
  458. PutStr (cwd) ;
  459. GotoXY (4, 1) ;
  460. Key ("W", "ork file: A:") ;
  461. PutStr (workName) ;
  462. GotoXY (5, 1) ;
  463. Key ("M", "ain file: A:") ;
  464. PutStr (mainName) ;
  465. GotoXY (7, 1) ;
  466. Key ("E", "dit ") ;
  467. Key ("C", "ompile ") ;
  468. Key ("R", "un ") ;
  469. Key ("S", "ave") ;
  470. GotoXY (9, 1) ;
  471. Key ("D", "ir ") ;
  472. Key ("Q", "uit compiler ") ;
  473. Key ("O", "ptions") ;
  474. GotoXY (11, 1) ;
  475. PutStr ("Text: ") ;
  476. PutCard (Length ()) ;
  477. PutStr (" bytes") ;
  478. freeB := TextLimit - Length ();
  479. GotoXY (12, 1) ;
  480. PutStr ("Free: ") ;
  481. PutCard (freeB) ;
  482. PutStr (" bytes") ;
  483. GotoXY (14, 1) ;
  484. Marked ;
  485. PutCh (">") ;
  486. Normal
  487. END DrawMenu ;
  488. (* ------------------------------------------------------------------ *)
  489. (* command handlers *)
  490. (* ------------------------------------------------------------------ *)
  491. PROCEDURE CmdLogDrive ;
  492. VAR nm : ARRAY [0..255] OF CHAR ;
  493. ln : CARDINAL ;
  494. BEGIN
  495. ClrScr ;
  496. GotoXY (1, 1) ;
  497. PutStr ("New drive: ") ;
  498. ln := ReadLine (nm) ;
  499. IF ln = 1 THEN
  500. drive := Upper (nm [0]) ;
  501. IF (drive < "A") OR (drive > "P") THEN
  502. drive := "A"
  503. END
  504. ELSIF ln > 1 THEN
  505. (* treat as a directory instead (linux has no real drives) *)
  506. IF chdir (ADR (nm)) # 0 THEN
  507. PutStr ("File not found") ;
  508. CrLf ;
  509. Pause
  510. END
  511. END
  512. END CmdLogDrive ;
  513. PROCEDURE CmdActDir ;
  514. VAR nm : ARRAY [0..255] OF CHAR ;
  515. BEGIN
  516. ClrScr ;
  517. GotoXY (1, 1) ;
  518. PutStr ("New directory: ") ;
  519. IF ReadLine (nm) > 0 THEN
  520. IF chdir (ADR (nm)) # 0 THEN
  521. PutStr ("File not found") ;
  522. CrLf ;
  523. Pause
  524. END
  525. END
  526. END CmdActDir ;
  527. PROCEDURE CmdWorkFile ;
  528. VAR nm : ARRAY [0..255] OF CHAR ;
  529. txtTitle : ARRAY [0..511] OF CHAR ;
  530. BEGIN
  531. ClrScr ;
  532. GotoXY (1, 1) ;
  533. PutStr ("Work file name: ") ;
  534. IF ReadLine (nm) > 0 THEN
  535. IF changed THEN
  536. CrLf ;
  537. PutStr (" ") ;
  538. IF Confirm ("Save current work file now (Y/N) ?") THEN
  539. SaveWorkFile
  540. END
  541. END ;
  542. ClrScr ;
  543. GotoXY (1, 1) ;
  544. SetWorkName (nm) ;
  545. StrClear (txtTitle) ;
  546. StrAppend (txtTitle, "Loading A:") ;
  547. StrAppend (txtTitle, workName) ;
  548. PutStr (txtTitle) ;
  549. CrLf ;
  550. LoadWorkFile
  551. END
  552. END CmdWorkFile ;
  553. PROCEDURE CmdMainFile ;
  554. VAR nm : ARRAY [0..255] OF CHAR ;
  555. BEGIN
  556. ClrScr ;
  557. GotoXY (1, 1) ;
  558. PutStr ("Main file name: ") ;
  559. IF ReadLine (nm) > 0 THEN
  560. StrCopy (mainName, nm) ;
  561. IF NOT HasExt (mainName) THEN
  562. StrAppend (mainName, ".PAS")
  563. END
  564. END
  565. END CmdMainFile ;
  566. PROCEDURE CmdCompile ;
  567. BEGIN
  568. ClrScr ;
  569. GotoXY (1, 1) ;
  570. PutStr ("Compiler under construction - press ESC") ;
  571. CrLf ;
  572. WaitEsc
  573. END CmdCompile ;
  574. PROCEDURE CmdRun ;
  575. BEGIN
  576. ClrScr ;
  577. GotoXY (1, 1) ;
  578. PutStr ("Compiler / interpreter under construction - press ESC") ;
  579. CrLf ;
  580. WaitEsc
  581. END CmdRun ;
  582. PROCEDURE CmdEditor ;
  583. VAR edChanged : BOOLEAN ;
  584. BEGIN
  585. IF StrLen (workName) = 0 THEN
  586. (* kgetfn: no work file yet -> prompt just like W does *)
  587. CmdWorkFile ;
  588. IF StrLen (workName) = 0 THEN
  589. RETURN
  590. END
  591. END ;
  592. edChanged := FALSE ;
  593. Run (drive, workName, edChanged) ;
  594. IF edChanged THEN
  595. changed := TRUE
  596. END
  597. END CmdEditor ;
  598. (* ------------------------------------------------------------------ *)
  599. (* TP3 "Options" submenu (optmenu) *)
  600. (* ------------------------------------------------------------------ *)
  601. PROCEDURE PutHex (n : CARDINAL) ;
  602. VAR dig : ARRAY [0..7] OF CHAR ;
  603. i, d : CARDINAL ;
  604. BEGIN
  605. i := 0 ;
  606. LOOP
  607. d := n MOD 16 ;
  608. IF d < 10 THEN
  609. dig [i] := CHR (ORD ("0") + d)
  610. ELSE
  611. dig [i] := CHR (ORD ("A") + d - 10)
  612. END ;
  613. n := n DIV 16 ;
  614. INC (i) ;
  615. IF (n = 0) OR (i = 8) THEN
  616. EXIT
  617. END
  618. END ;
  619. WHILE i > 0 DO
  620. DEC (i) ;
  621. PutCh (dig [i])
  622. END
  623. END PutHex ;
  624. PROCEDURE OptionsMenu ;
  625. VAR ch : CHAR ;
  626. s : ARRAY [0..255] OF CHAR ;
  627. done : BOOLEAN ;
  628. BEGIN
  629. done := FALSE ;
  630. REPEAT
  631. ClrScr ;
  632. GotoXY (1, 1) ;
  633. Marked ; PutCh ("M") ; Normal ;
  634. PutStr ("emory ") ;
  635. Marked ; PutCh ("C") ; Normal ;
  636. PutStr ("OM ") ;
  637. Marked ; PutCh ("H") ; Normal ;
  638. PutStr ("CHN") ;
  639. CrLf ;
  640. PutStr (" ") ;
  641. IF codeDest = 1 THEN
  642. PutStr ("Compile -> COM")
  643. ELSIF codeDest = 2 THEN
  644. PutStr ("Compile -> CHN")
  645. ELSE
  646. PutStr ("Compile -> Memory")
  647. END ;
  648. CrLf ;
  649. PutStr ("Text: ") ;
  650. PutCard (Length ()) ;
  651. PutStr (" Code: ") ;
  652. PutHex (minCode) ;
  653. PutStr (" Data: ") ;
  654. PutHex (minData) ;
  655. PutStr (" Stack: ") ;
  656. PutHex (minStack) ;
  657. CrLf ;
  658. PutStr ("Command line Params: ") ;
  659. PutStr (paramLine) ;
  660. CrLf ;
  661. Marked ; PutCh ("F") ; Normal ;
  662. PutStr ("ind run-time error ") ;
  663. Marked ; PutCh ("Q") ; Normal ;
  664. PutStr ("uit") ;
  665. CrLf ;
  666. CrLf ;
  667. Marked ; PutCh (">") ; Normal ;
  668. GetCh (ch) ;
  669. ch := Upper (ch) ;
  670. CASE ch OF
  671. | "M" : codeDest := 0
  672. | "C" : codeDest := 1
  673. | "H" : codeDest := 2
  674. | "O" :
  675. ClrScr ; GotoXY (1,1) ;
  676. PutStr ("Min Code Segment (hex): ") ;
  677. IF ReadLine (s) > 0 THEN minCode := 0 END
  678. | "D" :
  679. ClrScr ; GotoXY (1,1) ;
  680. PutStr ("Min Data Segment (hex): ") ;
  681. IF ReadLine (s) > 0 THEN minData := 0 END
  682. | "I" :
  683. ClrScr ; GotoXY (1,1) ;
  684. PutStr ("Min Free Dyn Mem / Stack (hex): ") ;
  685. IF ReadLine (s) > 0 THEN minStack := 0 END
  686. | "A" :
  687. ClrScr ; GotoXY (1,1) ;
  688. PutStr ("Max Free Dyn Mem / Stack (hex): ") ;
  689. IF ReadLine (s) > 0 THEN maxStack := 0 END
  690. | "P" :
  691. ClrScr ; GotoXY (1,1) ;
  692. PutStr ("Command line Params: ") ;
  693. IF ReadLine (paramLine) > 0 THEN
  694. (* keep the parameter string *)
  695. END
  696. | "F" :
  697. ClrScr ; GotoXY (1,1) ;
  698. PutStr ("Find run-time error address (hex) : ") ;
  699. IF ReadLine (s) > 0 THEN
  700. PutStr ("Searching ... (not implemented)") ;
  701. CrLf ;
  702. Pause
  703. END
  704. | "Q" :
  705. done := TRUE
  706. ELSE
  707. (* ignore *)
  708. END
  709. UNTIL done
  710. END OptionsMenu ;
  711. (* ------------------------------------------------------------------ *)
  712. PROCEDURE terminal ;
  713. VAR ch : CHAR ;
  714. BEGIN
  715. Open ;
  716. drive := "A" ;
  717. codeDest := 0 ;
  718. minCode := 0 ; minData := 0 ; minStack := 0 ; maxStack := 0 ;
  719. StrClear (workName) ;
  720. StrClear (mainName) ;
  721. StrClear (paramLine) ;
  722. Clear ;
  723. changed := FALSE ;
  724. LOOP
  725. DrawMenu ;
  726. GetCh (ch) ;
  727. ch := Upper (ch) ;
  728. CASE ch OF
  729. | "L" : CmdLogDrive
  730. | "A" : CmdActDir
  731. | "W" : CmdWorkFile
  732. | "M" : CmdMainFile
  733. | "E" : CmdEditor
  734. | "C" : CmdCompile
  735. | "R" : CmdRun
  736. | "S" :
  737. IF StrLen (workName) > 0 THEN
  738. SaveWorkFile ;
  739. Pause
  740. END
  741. | "D" : DirCmd
  742. | "O" : OptionsMenu
  743. | "Q" :
  744. IF changed THEN
  745. CrLf ;
  746. IF Confirm ("Work file not saved. Save (Y/N) ?") THEN
  747. SaveWorkFile
  748. END
  749. END ;
  750. Close ;
  751. HALT
  752. ELSE
  753. (* any other key: redraw the menu, like TP3 *)
  754. END
  755. END
  756. END terminal ;
  757. BEGIN
  758. terminal
  759. END Shell.