ncrt.inc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972
  1. {---------------------------------------------------------------------------
  2. CncWare
  3. (c) Copyright 1999-2000
  4. Portions copyright the FreePascal Team
  5. ---------------------------------------------------------------------------
  6. Filename..: ncrt.inc
  7. Programmer: Ken J. Wright, [email protected]
  8. Date......: 03/01/99
  9. Purpose - Code that is common to nCrt and oCrt.
  10. -------------------------------<< REVISIONS >>--------------------------------
  11. Ver | Date | Prog| Description
  12. -------+----------+-----+-----------------------------------------------------
  13. 2.00 | 12/13/99 | kjw | Initial Release.
  14. 2.02 | 12/15/99 | kjw | Removed use of endwin. Replaced with tcget/setattr.
  15. 2.03 | 12/16/99 | kjw | 1) Added shifted f-keys to nReadkey.
  16. | 2) Added raw & scrollok to StartCurses.
  17. | 3) Added alt'd keyset support.
  18. 2.04 | 01/04/00 | kjw | keypressed changed back to method of using getch
  19. | rather than select.
  20. 2.05 | 01/06/00 | kjw | 1) StartCurses now defaults to echo. Readkey sets to
  21. | noecho. This allows nCrt to handle echoing in the
  22. | default manor, but allows oCrt to control echoing
  23. | in the app with nEcho. Note: Read(ln) will always
  24. | echo as normal, regardless of any setting by nEcho.
  25. | Also set DoRefresh to true.
  26. | 2) nDelWindow now checks for stdscr or curscr and
  27. | makes sure that ActiveWn is not nil.
  28. | 3) Window() now moves to 1,1 and does not do a
  29. | clrscr.
  30. 2.06 | 01/11/00 | kjw | 1) Oops! 2.04 change went back to stdscr vs. ActiveWn.
  31. | Keypressed works correctly with windows again.
  32. | 2) ClrEol works correctly now with color.
  33. 2.07 | 01/31/00 | kjw | 1) Added NCRT_VERSION constants.
  34. | 2) Added prev_textattr to detect a change in
  35. | TextAttr value so current color gets updated.
  36. | 3) See ocrt.pp
  37. 2.08 | 06/09/00 | kjw | See ocrt.pp
  38. 2.08.01 | 06/11/2000 | kjw | See ocrt.pp
  39. 2.09.00 | 06/16/2000 | kjw | See ocrt.pp
  40. 2.10.00 | 06/16/2000 | kjw | See ocrt.pp
  41. 2.11.00 | 06/27/2000 | kjw
  42. | 1) See ocrt.pp
  43. | 2) Now uses ncurses for CrtRead so console control characters
  44. | work correctly (i.e., <ctrl/h>, <backspace>, etc.).
  45. 2.12.00 | 06/29/2000 | kjw | See ocrt.pp
  46. 2.13.00 | 06/30/2000 | kjw
  47. | Added nStop and nStart procedures.
  48. 2.14.00 | 07/05/2000 | kjw
  49. | 1) Added nCursor and nEscDelay functions.
  50. | 2) Added nInit and moved code from ncrt.pp & ocrt.pp to it.
  51. | 3) KEY_ALTMINUS & KEYALTEQUAL were reversed, but mapping ended
  52. | up correct.
  53. 2.15.00 | 1) Added nMaxRows & nMaxCols constants.
  54. | 2) See ocrt.pp
  55. 2.16.00 | 08/14/2000 | kjw | See ocrt.pp
  56. | 08/24/2000 | kjw |
  57. | 1) Added nTermName.
  58. | 2) Added CursesFailed.
  59. | 3) Moved all common initialization code to nInit.
  60. | 4) prev_textattr more reliable.
  61. ------------------------------------------------------------------------------
  62. }
  63. Procedure AssignCrt(var F: Text);
  64. Procedure ClrEol;
  65. Procedure ClrScr;
  66. Procedure ClrBot;
  67. Procedure Delay(DTime: Word);
  68. Procedure DelLine;
  69. Procedure GotoXY(x,y : integer);
  70. Procedure HighVideo;
  71. Procedure InsLine;
  72. Function Keypressed : boolean;
  73. Procedure LowVideo;
  74. Procedure NormVideo;
  75. Procedure NoSound;
  76. Function Readkey : char;
  77. Procedure Sound(hz : word);
  78. Procedure TextBackground(att : byte);
  79. Procedure TextColor(att : byte);
  80. Procedure TextMode(mode : word);
  81. Function WhereX : integer;
  82. Function WhereY : integer;
  83. Procedure Window(x,y,x1,y1 : integer);
  84. Procedure nStop;
  85. Procedure nStart;
  86. Function nCursor(c : integer) : integer;
  87. Function nEscDelay(d : longint) : longint;
  88. Function nTermName : string;
  89. Const
  90. NCRT_VERSION_MAJOR = 2;
  91. NCRT_VERSION_MINOR = 16;
  92. NCRT_VERSION_PATCH = 0;
  93. NCRT_VERSION = '2.16.00';
  94. { CRT modes }
  95. BW40 = 0; { 40x25 B/W on Color Adapter }
  96. CO40 = 1; { 40x25 Color on Color Adapter }
  97. BW80 = 2; { 80x25 B/W on Color Adapter }
  98. CO80 = 3; { 80x25 Color on Color Adapter }
  99. Mono = 7; { 80x25 on Monochrome Adapter }
  100. Font8x8 = 256; { Add-in for ROM font }
  101. { Mode constants for 3.0 compatibility }
  102. C40 = CO40;
  103. C80 = CO80;
  104. Black = 0;
  105. Blue = 1;
  106. Green = 2;
  107. Cyan = 3;
  108. Red = 4;
  109. Magenta = 5;
  110. Brown = 6;
  111. LightGray = 7;
  112. DarkGray = 8;
  113. LightBlue = 9;
  114. LightGreen = 10;
  115. LightCyan = 11;
  116. LightRed = 12;
  117. LightMagenta = 13;
  118. Yellow = 14;
  119. White = 15;
  120. Blink = 128;
  121. TextAttr : Byte = $07;
  122. LastMode : Word = 3;
  123. WindMin : Word = $0;
  124. WindMax : Word = $184f;
  125. { support for the alt'd characters }
  126. { these get initialized by StartCurses }
  127. KEY_ALTA = 465; { alt/a }
  128. KEY_ALTB = 466;
  129. KEY_ALTC = 467;
  130. KEY_ALTD = 468;
  131. KEY_ALTE = 469;
  132. KEY_ALTF = 470;
  133. KEY_ALTG = 471;
  134. KEY_ALTH = 472;
  135. KEY_ALTI = 473;
  136. KEY_ALTJ = 474;
  137. KEY_ALTK = 475;
  138. KEY_ALTL = 476;
  139. KEY_ALTM = 477;
  140. KEY_ALTN = 478;
  141. KEY_ALTO = 479;
  142. KEY_ALTP = 480;
  143. KEY_ALTQ = 481;
  144. KEY_ALTR = 482;
  145. KEY_ALTS = 483;
  146. KEY_ALTT = 484;
  147. KEY_ALTU = 485;
  148. KEY_ALTV = 486;
  149. KEY_ALTW = 487;
  150. KEY_ALTX = 488;
  151. KEY_ALTY = 489;
  152. KEY_ALTZ = 490; { alt/z }
  153. KEY_ALT1 = 491; { alt/1 }
  154. KEY_ALT2 = 492; { alt/2 }
  155. KEY_ALT3 = 493; { alt/3 }
  156. KEY_ALT4 = 494; { alt/4 }
  157. KEY_ALT5 = 495; { alt/5 }
  158. KEY_ALT6 = 496; { alt/6 }
  159. KEY_ALT7 = 497; { alt/7 }
  160. KEY_ALT8 = 498; { alt/8 }
  161. KEY_ALT9 = 499; { alt/9 }
  162. KEY_ALT0 = 500; { alt/0 }
  163. KEY_ALTMINUS = 501; { alt/- }
  164. KEY_ALTEQUAL = 502; { alt/= }
  165. KEY_ALTTAB = 503; { alt/tab }
  166. { cursor type }
  167. cOFF = 0; { invisible cursor }
  168. cON = 1; { normal cursor }
  169. cBIG = 2; { very visible cursor }
  170. { fullscreen size }
  171. nMaxRows : word = 25; { reset at startup to terminal setting }
  172. nMaxCols : word = 80; { for columns and rows }
  173. var
  174. CheckBreak,
  175. CheckEOF,
  176. CheckSnow,
  177. DirectVideo: Boolean;
  178. Implementation
  179. uses strings;
  180. Const
  181. { standard file descriptors }
  182. STDIN = 0;
  183. STDOUT = 1;
  184. STDERR = 2;
  185. Var
  186. ExitSave : pointer; { pointer to original exit proc }
  187. fg,bg : integer; { foreground & background }
  188. cp : array [0..7,0..7] of integer; { color pair array }
  189. ps : array [0..255] of char; { for use with pchars }
  190. doRefresh : boolean; { immediate refresh toggle }
  191. SubWn, { window created from window() }
  192. PrevWn, { previous window when active changes }
  193. ActiveWn : pwindow; { current active window for stdout }
  194. tmp_b : boolean;
  195. isEcho : boolean; { keeps track of echo status }
  196. MaxRows, { set at startup to terminal values }
  197. MaxCols : longint; { for columns and rows }
  198. tios : TermIOS; { saves the term settings at startup }
  199. prev_textattr : integer; { detect change in TextAttr }
  200. {==========================================================================
  201. This code chunk is from the FPC source tree in rtl/inc/textrec.inc.
  202. It is the internal format of a variable of type "Text" as defined and
  203. described in the Borland Pascal docs.
  204. ==========================================================================}
  205. const
  206. TextRecNameLength = 256;
  207. TextRecBufSize = 256;
  208. type
  209. TextBuf = array[0..TextRecBufSize-1] of char;
  210. TextRec = Packed Record
  211. Handle,
  212. Mode,
  213. bufsize,
  214. _private,
  215. bufpos,
  216. bufend : longint;
  217. bufptr : ^textbuf;
  218. openfunc,
  219. inoutfunc,
  220. flushfunc,
  221. closefunc : pointer;
  222. UserData : array[1..16] of byte;
  223. name : array[0..textrecnamelength-1] of char;
  224. buffer : textbuf;
  225. End;
  226. {==========================================================================}
  227. { set the active window for write(ln), read(ln) }
  228. Procedure SetActiveWn(win : pwindow);
  229. Begin
  230. If win <> ActiveWn Then PrevWn := ActiveWn;
  231. { don't set to a nil window! }
  232. If win <> Nil Then
  233. ActiveWn := win
  234. Else
  235. ActiveWn := stdscr;
  236. End;
  237. {--------------------------------------------
  238. initialize ncurses screen & keyboard, and
  239. return a pointer to stdscr.
  240. NOTE: This is done at unit initialization.
  241. --------------------------------------------}
  242. Function StartCurses(var win : pWindow) : Boolean;
  243. Var
  244. i : integer;
  245. s : string[3];
  246. Begin
  247. { save the current terminal settings }
  248. tcGetAttr(STDIN,tios);
  249. if initscr=Nil then Begin
  250. StartCurses := false;
  251. win := nil;
  252. Exit;
  253. End Else Begin
  254. StartCurses := true;
  255. start_color;
  256. cbreak; { disable keyboard buffering }
  257. raw; { disable flow control, etc. }
  258. echo; { echo keypresses }
  259. nonl; { don't process cr in newline }
  260. intrflush(stdscr,bool(false));
  261. keypad(stdscr,bool(true));
  262. scrollok(stdscr,bool(true));
  263. win := stdscr;
  264. isEcho := true;
  265. doRefresh := true;
  266. getmaxyx(stdscr,MaxRows,MaxCols);
  267. { make these values visible to apps }
  268. nMaxRows := MaxRows;
  269. nMaxCols := MaxCols;
  270. { define the the alt'd keysets for ncurses }
  271. { alt/a .. atl/z }
  272. for i := ord('a') to ord('z') do Begin
  273. s := #27+chr(i)+#0;
  274. define_key(@s[1],(KEY_ALTA-97)+i);
  275. End;
  276. { alt/1 .. alt/9 }
  277. for i := 1 to 9 do Begin
  278. s := #27+chr(i)+#0;
  279. define_key(@s[1],(KEY_ALT1-1)+i);
  280. End;
  281. s := #27+'0'+#0; define_key(@s[1],KEY_ALT0); { alt/0 }
  282. s := #27+'-'+#0; define_key(@s[1],KEY_ALTMINUS); { alt/- }
  283. s := #27+'='+#0; define_key(@s[1],KEY_ALTEQUAL); { alt/= }
  284. s := #27+#9+#0; define_key(@s[1],KEY_ALTTAB); { alt/tab }
  285. End;
  286. End;
  287. {----------------------------------
  288. Shutdown ncurses.
  289. NOTE: This is done via ExitProc.
  290. ----------------------------------}
  291. Procedure EndCurses;
  292. Begin
  293. { restore the original terminal settings }
  294. { and leave the screen how the app left it }
  295. tcSetAttr(STDIN,TCSANOW,tios);
  296. End;
  297. {--------------------------------------------------------
  298. This disables any curses activity until a refresh.
  299. Use this BEFORE any shelling (shell,exec,execv,etc)
  300. to put the terminal temporarily back into cooked mode.
  301. --------------------------------------------------------}
  302. Procedure nStop;
  303. Begin
  304. endwin;
  305. End;
  306. {---------------------------------------------
  307. Simply a refresh to re-establish the curses
  308. terminal settings following an nStop.
  309. ---------------------------------------------}
  310. Procedure nStart;
  311. Begin
  312. refresh;
  313. End;
  314. { see if the specified attribute is high intensity }
  315. Function nIsBold(att : integer) : boolean;
  316. Begin
  317. bg := att div 16;
  318. fg := att - (bg * 16);
  319. nisbold := (fg > 7);
  320. End;
  321. { map a curses color to an ibm color }
  322. Function c2ibm(c : integer) : integer;
  323. { ncurses constants
  324. COLOR_BLACK = 0;
  325. COLOR_RED = 1;
  326. COLOR_GREEN = 2;
  327. COLOR_YELLOW = 3;
  328. COLOR_BLUE = 4;
  329. COLOR_MAGENTA = 5;
  330. COLOR_CYAN = 6;
  331. COLOR_WHITE = 7;
  332. }
  333. Var
  334. att : integer;
  335. Begin
  336. Case c of
  337. COLOR_BLACK : att := black;
  338. COLOR_RED : att := red;
  339. COLOR_GREEN : att := green;
  340. COLOR_YELLOW : att := brown;
  341. COLOR_BLUE : att := blue;
  342. COLOR_MAGENTA : att := magenta;
  343. COLOR_CYAN : att := cyan;
  344. COLOR_WHITE : att := lightgray;
  345. else att := c;
  346. End;
  347. c2ibm := att;
  348. End;
  349. { map an ibm color to a curses color }
  350. Function ibm2c(c : integer) : integer;
  351. Var
  352. att : integer;
  353. Begin
  354. Case c of
  355. black : att := COLOR_BLACK;
  356. red : att := COLOR_RED;
  357. green : att := COLOR_GREEN;
  358. brown : att := COLOR_YELLOW;
  359. blue : att := COLOR_BLUE;
  360. magenta : att := COLOR_MAGENTA;
  361. cyan : att := COLOR_CYAN;
  362. lightgray : att := COLOR_WHITE;
  363. else att := c;
  364. End;
  365. ibm2c := att;
  366. End;
  367. { initialize a color pair }
  368. Function nSetColorPair(att : integer) : integer;
  369. var
  370. i : integer;
  371. Begin
  372. bg := att div 16;
  373. fg := att - (bg * 16);
  374. While bg > 7 Do dec(bg,8);
  375. While fg > 7 Do dec(fg,8);
  376. bg := ibm2c(bg);
  377. fg := ibm2c(fg);
  378. i := cp[bg,fg];
  379. init_pair(i,fg,bg);
  380. nSetColorPair := i;
  381. End;
  382. { map a standard color attribute to an ncurses attribute }
  383. Function CursesAtts(att : byte) : longint;
  384. Var
  385. atts : longint;
  386. Begin
  387. atts := COLOR_PAIR(nSetColorPair(att));
  388. If nIsBold(att) Then atts := atts or A_BOLD;
  389. If (att and $80) = $80 Then atts := atts or A_BLINK;
  390. CursesAtts := atts;
  391. End;
  392. {------------------------------------------------
  393. Delete a window.
  394. NOTE: This does not clear it from the display.
  395. ------------------------------------------------}
  396. Procedure nDelWindow(var win : pWindow);
  397. Begin
  398. If (win = stdscr) or (win = curscr) Then Exit;
  399. If win <> Nil Then delwin(win);
  400. win := Nil;
  401. If ActiveWn = Nil Then SetActiveWn(stdscr);
  402. End;
  403. {-----------------------------------------
  404. Set the current text color of a window,
  405. delayed until next refresh.
  406. -----------------------------------------}
  407. Procedure nWinColor(win : pWindow; att : integer);
  408. Begin
  409. wattrset(win,CursesAtts(att));
  410. prev_textattr := att;
  411. End;
  412. { clear the specified window }
  413. procedure nClrScr(win : pWindow; att : integer);
  414. Begin
  415. wbkgd(win,CursesAtts(att));
  416. TouchWin(win);
  417. werase(win);
  418. If doRefresh Then wrefresh(win);
  419. prev_textattr := att;
  420. End;
  421. { clear from the cursor to the end of line in a window }
  422. Procedure nClrEol(win : pWindow);
  423. Var
  424. tmp : pwindow;
  425. x,y,
  426. xb,yb,
  427. xm,ym : longint;
  428. Begin
  429. {--------------------------------------------------------
  430. In order to have the correct color, we must define and
  431. clear a temporary window. ncurses wclrtoeol() uses the
  432. window background color rather that the current color
  433. attribute ;-(
  434. --------------------------------------------------------}
  435. getyx(win,y,x);
  436. getbegyx(win,yb,xb);
  437. getmaxyx(win,ym,xm);
  438. tmp := subwin(win,1,xm-x,yb+y,xb+x);
  439. If tmp = nil then Exit;
  440. wbkgd(tmp,CursesAtts(TextAttr));
  441. werase(tmp);
  442. { wclrtoeol(win);}
  443. If doRefresh Then wrefresh(tmp);
  444. delwin(tmp);
  445. End;
  446. { clear from the cursor to the bottom in a window }
  447. Procedure nClrBot(win : pWindow);
  448. Begin
  449. wclrtobot(win);
  450. If doRefresh Then wrefresh(win);
  451. End;
  452. { insert a line at the cursor line in a window }
  453. Procedure nInsLine(win : pWindow);
  454. Begin
  455. winsertln(win);
  456. If doRefresh Then wrefresh(win);
  457. End;
  458. { delete line at the cursor in a window }
  459. Procedure nDelLine(win : pWindow);
  460. Begin
  461. wdeleteln(win);
  462. If doRefresh Then wrefresh(win);
  463. End;
  464. { position cursor in a window }
  465. Procedure nGotoXY(win : pWindow; x,y : integer);
  466. Begin
  467. wmove(win,y-1,x-1);
  468. touchwin(win);
  469. If doRefresh Then wrefresh(win);
  470. End;
  471. { find cursor x position in a window }
  472. Function nWhereX(win : pWindow) : integer;
  473. var x,y : longint;
  474. Begin
  475. getyx(win,y,x);
  476. nWhereX := x+1;
  477. End;
  478. { find cursor y position in a window }
  479. Function nWhereY(win : pWindow) : integer;
  480. var x,y : longint;
  481. Begin
  482. getyx(win,y,x);
  483. nWhereY := y+1;
  484. End;
  485. {---------------------------------------------------------------------
  486. read a keystroke from a window, including function keys and extended
  487. keys (arrows, etc.)
  488. Note: Make sure that keypad(win,true) has been issued prior to use.
  489. ( nWindow does this )
  490. ---------------------------------------------------------------------}
  491. Function nReadkey(win : pWindow) : char;
  492. var
  493. c : char;
  494. l : longint;
  495. xtnded : boolean;
  496. Begin
  497. l := wgetch(win);
  498. { if it's an extended key, then map to the IBM values }
  499. if l > 255 then begin
  500. xtnded := true;
  501. c := #27;
  502. Case l of
  503. KEY_BREAK : Begin xtnded := false; c := #3; End;
  504. KEY_BACKSPACE : Begin xtnded := false; c := #8; End;
  505. KEY_IC : c := #82; { insert }
  506. KEY_DC : c := #83; { delete }
  507. KEY_HOME : c := #71; { home }
  508. KEY_END : c := #79; { end }
  509. KEY_UP : c := #72; { up arrow }
  510. KEY_DOWN : c := #80; { down arrow }
  511. KEY_LEFT : c := #75; { left arrow }
  512. KEY_RIGHT : c := #77; { right arrow }
  513. KEY_NPAGE : c := #81; { page down }
  514. KEY_PPAGE : c := #73; { page up }
  515. KEY_ALTA : c := #30; { alt/a }
  516. KEY_ALTB : c := #48;
  517. KEY_ALTC : c := #46;
  518. KEY_ALTD : c := #32;
  519. KEY_ALTE : c := #18;
  520. KEY_ALTF : c := #33;
  521. KEY_ALTG : c := #34;
  522. KEY_ALTH : c := #35;
  523. KEY_ALTI : c := #23;
  524. KEY_ALTJ : c := #36;
  525. KEY_ALTK : c := #37;
  526. KEY_ALTL : c := #38;
  527. KEY_ALTM : c := #50;
  528. KEY_ALTN : c := #49;
  529. KEY_ALTO : c := #24;
  530. KEY_ALTP : c := #25;
  531. KEY_ALTQ : c := #16;
  532. KEY_ALTR : c := #19;
  533. KEY_ALTS : c := #31;
  534. KEY_ALTT : c := #20;
  535. KEY_ALTU : c := #22;
  536. KEY_ALTV : c := #47;
  537. KEY_ALTW : c := #17;
  538. KEY_ALTX : c := #45;
  539. KEY_ALTY : c := #21;
  540. KEY_ALTZ : c := #44; { alt/z }
  541. KEY_ALT1 : c := #120; { alt/1 }
  542. KEY_ALT2 : c := #121; { alt/2 }
  543. KEY_ALT3 : c := #122; { alt/3 }
  544. KEY_ALT4 : c := #123; { alt/4 }
  545. KEY_ALT5 : c := #124; { alt/5 }
  546. KEY_ALT6 : c := #125; { alt/6 }
  547. KEY_ALT7 : c := #126; { alt/7 }
  548. KEY_ALT8 : c := #127; { alt/8 }
  549. KEY_ALT9 : c := #128; { alt/9 }
  550. KEY_ALT0 : c := #129; { alt/0 }
  551. KEY_ALTMINUS : c := #130; { alt/- }
  552. KEY_ALTEQUAL : c := #131; { alt/= }
  553. KEY_ALTTAB : c := #15; { alt/tab }
  554. Else
  555. Begin
  556. If l = Key_f(1) Then c := #59 Else
  557. If l = Key_f(2) Then c := #60 Else
  558. If l = Key_f(3) Then c := #61 Else
  559. If l = Key_f(4) Then c := #62 Else
  560. If l = Key_f(5) Then c := #63 Else
  561. If l = Key_f(6) Then c := #64 Else
  562. If l = Key_f(7) Then c := #65 Else
  563. If l = Key_f(8) Then c := #66 Else
  564. If l = Key_f(9) Then c := #67 Else
  565. If l = Key_f(10) Then c := #68 Else
  566. If l = Key_f(11) Then c := #84 Else
  567. If l = Key_f(12) Then c := #85 Else
  568. If l = Key_f(13) Then c := #86 Else
  569. If l = Key_f(14) Then c := #87 Else
  570. If l = Key_f(15) Then c := #88 Else
  571. If l = Key_f(16) Then c := #89 Else
  572. If l = Key_f(17) Then c := #90 Else
  573. If l = Key_f(18) Then c := #91 Else
  574. If l = Key_f(19) Then c := #92 Else
  575. If l = Key_f(20) Then c := #93;
  576. End;
  577. End;
  578. If xtnded Then Begin
  579. nReadKey := #0;
  580. ungetch(ord(c));
  581. Exit;
  582. End Else
  583. nReadkey := c;
  584. End Else
  585. nReadkey := chr(ord(l));
  586. End;
  587. { write a string to a window at the current cursor position }
  588. Procedure nWrite(win : pWindow; s : string);
  589. Begin
  590. If TextAttr <> prev_textattr Then
  591. nWinColor(win,TextAttr);
  592. waddstr(win,StrPCopy(ps,s));
  593. If doRefresh Then wrefresh(win);
  594. End;
  595. {=========================================================================
  596. CrtWrite, CrtRead, CrtReturn, CrtClose, CrtOpen, AssignCrt.
  597. These functions come from the FPC distribution rtl/linux/crt unit.
  598. These are the hooks into the input/output stream needed for write(ln)
  599. and read(ln).
  600. =========================================================================}
  601. { used by CrtWrite }
  602. Procedure DoWrite(temp : string);
  603. Begin
  604. nWrite(ActiveWn,temp);
  605. End;
  606. Function CrtWrite(Var F: TextRec): Integer;
  607. {
  608. Top level write function for CRT
  609. }
  610. Var
  611. Temp : String;
  612. idx,i : Longint;
  613. { oldflush : boolean;}
  614. Begin
  615. { oldflush:=ttySetFlush(Flushing);}
  616. idx:=0;
  617. while (F.BufPos>0) do
  618. begin
  619. i:=F.BufPos;
  620. if i>255 then
  621. i:=255;
  622. system.Move(F.BufPTR^[idx],Temp[1],F.BufPos);
  623. Temp[0]:=Chr(i);
  624. DoWrite(Temp);
  625. dec(F.BufPos,i);
  626. inc(idx,i);
  627. end;
  628. { ttySetFlush(oldFLush);}
  629. CrtWrite:=0;
  630. End;
  631. Function CrtRead(Var F: TextRec): Integer;
  632. {
  633. Read from CRT associated file.
  634. }
  635. Begin
  636. { let's use ncurses instead! }
  637. FillChar(F.BufPtr^, F.BufSize, #0);
  638. wgetnstr(ActiveWn,F.BufPtr^, F.BufSize-1);
  639. F.BufEnd := Length(StrPas(F.BufPtr^))+1;
  640. F.BufPtr^[F.BufEnd-1] := #10;
  641. F.BufPos:=0;
  642. { CrtWrite(F);}
  643. CrtRead:=0;
  644. End;
  645. Function CrtReturn(Var F:TextRec):Integer;
  646. Begin
  647. F.BufEnd := 0;
  648. F.BufPos:= 0;
  649. CrtReturn:=0;
  650. end;
  651. Function CrtClose(Var F: TextRec): Integer;
  652. {
  653. Close CRT associated file.
  654. }
  655. Begin
  656. F.Mode:=fmClosed;
  657. CrtClose:=0;
  658. End;
  659. Function CrtOpen(Var F: TextRec): Integer;
  660. {
  661. Open CRT associated file.
  662. }
  663. Begin
  664. If F.Mode=fmOutput Then
  665. begin
  666. TextRec(F).InOutFunc:=@CrtWrite;
  667. TextRec(F).FlushFunc:=@CrtWrite;
  668. end
  669. Else
  670. begin
  671. F.Mode:=fmInput;
  672. TextRec(F).InOutFunc:=@CrtRead;
  673. TextRec(F).FlushFunc:=@CrtReturn;
  674. end;
  675. TextRec(F).CloseFunc:=@CrtClose;
  676. CrtOpen:=0;
  677. End;
  678. procedure AssignCrt(var F: Text);
  679. {
  680. Assign a file to the console. All output on file goes to console instead.
  681. }
  682. begin
  683. Assign(F,'');
  684. TextRec(F).OpenFunc:=@CrtOpen;
  685. end;
  686. {==========================================================================
  687. Standard crt unit replacements
  688. ==========================================================================}
  689. { set the text background color }
  690. Procedure TextBackground(att : byte);
  691. Begin
  692. TextAttr:=
  693. ((att shl 4) and ($f0 and not Blink)) or (TextAttr and ($0f OR Blink) );
  694. nWinColor(ActiveWn,TextAttr);
  695. End;
  696. { set the text foreground color }
  697. Procedure TextColor(att : byte);
  698. Begin
  699. TextAttr := (att and $8f) or (TextAttr and $70);
  700. nWinColor(ActiveWn,TextAttr);
  701. End;
  702. { set to high intensity }
  703. Procedure HighVideo;
  704. Begin
  705. TextColor(TextAttr Or $08);
  706. End;
  707. { set to low intensity }
  708. Procedure LowVideo;
  709. Begin
  710. TextColor(TextAttr And $77);
  711. End;
  712. { set to normal display colors }
  713. Procedure NormVideo;
  714. Begin
  715. TextColor(7);
  716. TextBackGround(0);
  717. End;
  718. { clear stdscr }
  719. Procedure ClrScr;
  720. Begin
  721. nClrScr(ActiveWn,TextAttr);
  722. End;
  723. { clear from the cursor to the end of line in stdscr }
  724. Procedure ClrEol;
  725. Begin
  726. nClrEol(ActiveWn);
  727. End;
  728. { clear from the cursor to the bottom of stdscr }
  729. Procedure ClrBot;
  730. Begin
  731. nClrBot(ActiveWn);
  732. End;
  733. { insert a line at the cursor line in stdscr }
  734. Procedure InsLine;
  735. Begin
  736. nInsLine(ActiveWn);
  737. End;
  738. { delete line at the cursor in stdscr }
  739. Procedure DelLine;
  740. Begin
  741. nDelLine(ActiveWn);
  742. End;
  743. { position cursor in stdscr }
  744. Procedure GotoXY(x,y : integer);
  745. Begin
  746. nGotoXY(ActiveWn,x,y);
  747. End;
  748. { find cursor x position in stdscr }
  749. Function WhereX : integer;
  750. Begin
  751. WhereX := nWhereX(ActiveWn);
  752. End;
  753. { find cursor y position in stdscr }
  754. Function WhereY : integer;
  755. Begin
  756. WhereY := nWhereY(ActiveWn);
  757. End;
  758. { Wait for DTime milliseconds }
  759. Procedure Delay(DTime: Word);
  760. Begin
  761. Select(0,nil,nil,nil,DTime);
  762. End;
  763. { create a new subwindow of stdscr }
  764. Procedure Window(x,y,x1,y1 : integer);
  765. Begin
  766. nDelWindow(SubWn);
  767. SubWn := subwin(stdscr,y1-y+1,x1-x+1,y-1,x-1);
  768. If SubWn = nil then Exit;
  769. intrflush(SubWn,bool(false));
  770. keypad(SubWn,bool(true));
  771. scrollok(SubWn,bool(true));
  772. SetActiveWn(SubWn);
  773. GotoXY(1,1);
  774. End;
  775. {------------------------------------------------------
  776. Check if a key has been pressed.
  777. Note: this is best used along with select() on STDIN,
  778. as it can suck up lots of cpu time.
  779. Better yet, use nKeypressed instead if you don't need
  780. to include file descriptors other than STDIN.
  781. ------------------------------------------------------}
  782. function Keypressed : boolean;
  783. var
  784. l : longint;
  785. { fd : fdSet;}
  786. Begin
  787. Keypressed := FALSE;
  788. nodelay(ActiveWn,bool(TRUE));
  789. l := wgetch(ActiveWn);
  790. If l <> ERR Then Begin { ERR = -(1) from unit ncurses }
  791. ungetch(l);
  792. Keypressed := TRUE;
  793. End;
  794. nodelay(ActiveWn,bool(FALSE));
  795. { Below is more efficient code, but does not work well with
  796. nReadkey & extended keys because nReadkey's ungetch does not
  797. force a change in STDIN. So, a "while keypressed" block does
  798. not produce the expected results when trapping for char(0)
  799. followed by a second scan code.
  800. FD_Zero(fd);
  801. fd_Set(STDIN,fd);
  802. Keypressed := (Select(STDIN+1,@fd,nil,nil,0) > 0);
  803. }
  804. End;
  805. { silently read a key from stdscr }
  806. Function Readkey : char;
  807. Begin
  808. tmp_b := IsEcho;
  809. noecho;
  810. Readkey := nReadkey(ActiveWn);
  811. If tmp_b Then echo;
  812. End;
  813. { a cheap replacement! }
  814. Procedure Sound(hz : word);
  815. Begin
  816. Beep;
  817. wrefresh(ActiveWn);
  818. End;
  819. Procedure NoSound;
  820. Begin
  821. End;
  822. Procedure TextMode(mode : word);
  823. Begin
  824. nDelWindow(SubWn);
  825. SetActiveWn(stdscr);
  826. LastMode := mode;
  827. DirectVideo := true;
  828. CheckSnow := true;
  829. NormVideo;
  830. ClrScr;
  831. End;
  832. { Set the cursor visibility. Returns the previous value }
  833. { or (-1) if value c is not supported by the terminal. }
  834. Function nCursor(c : integer) : integer;
  835. Begin
  836. nCursor := curs_set(c);
  837. End;
  838. { Set the <esc> key delay time in milliseconds. }
  839. { Use d=(-1) to return current value without updating. }
  840. Function nEscDelay(d : longint) : longint;
  841. Begin
  842. nEscDelay := ESCDELAY;
  843. If d >= 0 Then ESCDELAY := d;
  844. End;
  845. { return the current terminal name (same as $TERM env variable) }
  846. Function nTermName : string;
  847. Begin
  848. nTermName := StrPas(termname);
  849. End;
  850. { could not initialize ncurses }
  851. Procedure CursesFailed;
  852. Begin
  853. { give 'em a clue! }
  854. Writeln('StartCurses() failed');
  855. Halt;
  856. End;
  857. { exit procedure to ensure curses is closed up cleanly }
  858. Procedure nExit;
  859. Begin
  860. ExitProc := ExitSave;
  861. EndCurses;
  862. End;
  863. Procedure nInit;
  864. Begin
  865. { set the unit exit procedure }
  866. ExitSave := ExitProc;
  867. ExitProc := @nExit;
  868. { load the color pairs array with color pair indices (0..63 }
  869. For bg := 0 to 7 Do For fg := 0 to 7 do cp[bg,fg] := (bg*8)+fg;
  870. { initial window pointers }
  871. SubWn := nil;
  872. PrevWn := ActiveWn;
  873. { basic gray on black screen }
  874. TextMode(LastMode);
  875. { Redirect the standard output }
  876. assigncrt(Output);
  877. Rewrite(Output);
  878. TextRec(Output).Handle:=StdOutputHandle;
  879. { Redirect the standard input }
  880. assigncrt(Input);
  881. Reset(Input);
  882. TextRec(Input).Handle:=StdInputHandle;
  883. { some defaults }
  884. nEscDelay(500); { default is 1000 (1 second) }
  885. nCursor(cON); { normal cursor }
  886. End;
  887. {
  888. $Log$
  889. Revision 1.3 2000-08-29 05:51:09 michael
  890. + Merged changes and additions from fixbranch
  891. Revision 1.2 2000/07/13 11:33:27 michael
  892. + removed logs
  893. }