crt.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. {****************************************************************************
  2. $Id$
  3. Standard CRT unit.
  4. Free Pascal runtime library for OS/2.
  5. Copyright (c) 1997 Daniel Mantione.
  6. This file may be reproduced and modified under the same conditions
  7. as all other Free Pascal source code.
  8. ****************************************************************************}
  9. unit crt;
  10. interface
  11. uses dos;
  12. const
  13. _40cols=0;
  14. _80cols=1;
  15. _132cols=2;
  16. _25rows=0;
  17. _28rows=16;
  18. _43rows=32;
  19. _50rows=48;
  20. font8x8=_50rows;
  21. black =0;
  22. blue =1;
  23. green =2;
  24. cyan =3;
  25. red =4;
  26. magenta =5;
  27. brown =6;
  28. lightgray =7;
  29. darkgray =8;
  30. lightblue =9;
  31. lightgreen =10;
  32. lightcyan =11;
  33. lightred =12;
  34. lightmagenta =13;
  35. yellow =14;
  36. white =15;
  37. blink =128;
  38. {cemodeset means that the procedure textmode has failed to set up a mode.}
  39. type cexxxx=(cenoerror,cemodeset);
  40. var textattr:byte; {Text attribute. RW}
  41. windmin,windmax:word; {Window coordinates. R-}
  42. lastmode:word; {Last videomode. R-}
  43. crt_error:cexxxx; {Crt-status. RW}
  44. function keypressed:boolean;
  45. function readkey:char;
  46. procedure clrscr;
  47. procedure clreol;
  48. function whereX:byte;
  49. function whereY:byte;
  50. procedure gotoXY(x,y:byte);
  51. procedure window(left,top,right,bottom : byte);
  52. procedure textmode(mode:integer);
  53. procedure textcolor(colour:byte);
  54. procedure textbackground(colour:byte);
  55. procedure insline;
  56. procedure delline;
  57. procedure lowvideo;
  58. procedure normvideo;
  59. procedure highvideo;
  60. procedure assigncrt(var f:text);
  61. procedure delay(ms:word);
  62. procedure sound(hz:word);
  63. procedure nosound;
  64. {***************************************************************************}
  65. {***************************************************************************}
  66. implementation
  67. const extkeycode:char=#0;
  68. var maxrows,maxcols:word;
  69. type Tkbdkeyinfo=record
  70. charcode,scancode:char;
  71. fbstatus,bnlsshift:byte;
  72. fsstate:word;
  73. time:longint;
  74. end;
  75. {if you have information on the folowing datastructure, please
  76. send them to me at [email protected]}
  77. {This datastructure is needed when we ask in what video mode we are,
  78. or we want to set up a new mode.}
  79. viomodeinfo=record
  80. cb:word; { length of the entire data
  81. structure }
  82. fbtype, { bit mask of mode being set}
  83. color: byte; { number of colors (power of 2) }
  84. col, { number of text columns }
  85. row, { number of text rows }
  86. hres, { horizontal resolution }
  87. vres: word; { vertical resolution }
  88. fmt_ID, { attribute format
  89. ! more info wanted !}
  90. attrib: byte; { number of attributes }
  91. buf_addr, { physical address of
  92. videobuffer, e.g. $0b800}
  93. buf_length, { length of a videopage (bytes)}
  94. full_length, { total video-memory on video-
  95. card (bytes)}
  96. partial_length:longint; { ????? info wanted !}
  97. ext_data_addr:pointer; { ????? info wanted !}
  98. end;
  99. {EMXWRAP.DLL has strange calling conventions: All parameters must have
  100. a 4 byte size.}
  101. function kbdcharin(var Akeyrec:Tkbdkeyinfo;wait,kbdhandle:longint):word; cdecl;
  102. external 'EMXWRAP' index 204;
  103. function kbdpeek(var Akeyrec:TkbdkeyInfo;kbdhandle:word):word; cdecl;
  104. external 'EMXWRAP' index 222;
  105. function dossleep(time:cardinal):word; cdecl;
  106. external 'DOSCALLS' index 229;
  107. function vioscrollup(top,left,bottom,right,lines:longint;
  108. var screl:word;viohandle:longint):word; cdecl;
  109. external 'EMXWRAP' index 107;
  110. function vioscrolldn(top,left,bottom,right,lines:longint;
  111. var screl:word;viohandle:longint):word; cdecl;
  112. external 'EMXWRAP' index 147;
  113. function viogetcurpos(var row,column:word;viohandle:longint):word; cdecl;
  114. external 'EMXWRAP' index 109;
  115. function viosetcurpos(row,column,viohandle:longint):word; cdecl;
  116. external 'EMXWRAP' index 115;
  117. function viowrtcharstratt(s:Pchar;len,row,col:longint;var attr:byte;
  118. viohandle:longint):word; cdecl;
  119. external 'EMXWRAP' index 148;
  120. function viogetmode(var Amodeinfo:viomodeinfo;viohandle:longint):word; cdecl;
  121. external 'EMXWRAP' index 121;
  122. function viosetmode(var Amodeinfo:viomodeinfo;viohandle:longint):word; cdecl;
  123. external 'EMXWRAP' index 122;
  124. procedure setscreenmode(mode:word);
  125. { This procedure sets a new videomode. Note that the constants passes to
  126. this procedure are different than in the dos mode.}
  127. const modecols:array[0..2] of word=(40,80,132);
  128. moderows:array[0..3] of word=(25,28,43,50);
  129. var newmode:viomodeinfo;
  130. begin
  131. newmode.cb:=8;
  132. newmode.fbtype:=1; {Non graphics colour mode.}
  133. newmode.color:=4; {We want 16 colours, 2^4=16.}
  134. newmode.col:=modecols[mode and 15];
  135. newmode.row:=moderows[mode shr 4];
  136. if viosetmode(newmode,0)=0 then
  137. crt_error:=cenoerror
  138. else
  139. crt_error:=cemodeset;
  140. maxcols:=newmode.col;
  141. maxrows:=newmode.row;
  142. end;
  143. procedure getcursor(var y,x:word);
  144. {Get the cursor position.}
  145. begin
  146. viogetcurpos(y,x,0)
  147. end;
  148. procedure setcursor(y,x:word);
  149. {Set the cursor position.}
  150. begin
  151. viosetcurpos(y,x,0)
  152. end;
  153. procedure scroll_up(top,left,bottom,right,lines:word;var screl:word);
  154. begin
  155. vioscrollup(top,left,bottom,right,lines,screl,0)
  156. end;
  157. procedure scroll_dn(top,left,bottom,right,lines:word;var screl:word);
  158. begin
  159. vioscrolldn(top,left,bottom,right,lines,screl,0)
  160. end;
  161. function keypressed:boolean;
  162. {Checks if a key is pressed.}
  163. var Akeyrec:Tkbdkeyinfo;
  164. begin
  165. kbdpeek(Akeyrec,0);
  166. keypressed:=(extkeycode<>#0) or ((Akeyrec.fbstatus and $40)<>0);
  167. end;
  168. function readkey:char;
  169. {Reads the next character from the keyboard.}
  170. var Akeyrec:Tkbdkeyinfo;
  171. c,s:char;
  172. begin
  173. if extkeycode<>#0 then
  174. begin
  175. readkey:=extkeycode;
  176. extkeycode:=#0
  177. end
  178. else
  179. begin
  180. kbdcharin(Akeyrec,0,0);
  181. c:=Akeyrec.charcode;
  182. s:=Akeyrec.scancode;
  183. if (c=#224) and (s<>#0) then
  184. c:=#0;
  185. if c=#0 then
  186. extkeycode:=s;
  187. readkey:=c;
  188. end;
  189. end;
  190. procedure clrscr;
  191. {Clears the current window.}
  192. var screl:word;
  193. begin
  194. screl:=$20+textattr shl 8;
  195. scroll_up(hi(windmin),lo(windmin),
  196. hi(windmax),lo(windmax),
  197. hi(windmax)-hi(windmin)+1,
  198. screl);
  199. gotoXY(1,1);
  200. end;
  201. procedure gotoXY(x,y:byte);
  202. {Positions the cursor on (x,y) relative to the window origin.}
  203. begin
  204. if x<1 then
  205. x:=1;
  206. if y<1 then
  207. y:=1;
  208. if y+hi(windmin)-2>=hi(windmax) then
  209. y:=hi(windmax)-hi(windmin)+1;
  210. if x+lo(windmin)-2>=lo(windmax) then
  211. x:=lo(windmax)-lo(windmin)+1;
  212. setcursor(y+hi(windmin)-1,x+lo(windmin)-1);
  213. end;
  214. function whereX:byte;
  215. {Returns the x position of the cursor.}
  216. var x,y:word;
  217. begin
  218. getcursor(y,x);
  219. whereX:=x-lo(windmin)+1;
  220. end;
  221. function whereY:byte;
  222. {Returns the y position of the cursor.}
  223. var x,y:word;
  224. begin
  225. getcursor(y,x);
  226. whereY:=y-hi(windmin)+1;
  227. end;
  228. procedure clreol;
  229. {Clear from current position to end of line.
  230. Contributed by Michail A. Baikov}
  231. var i:byte;
  232. begin
  233. {not fastest, but compatible}
  234. for i:=wherex to lo(windmax) do write(' ');
  235. gotoxy(1,wherey); {may be not}
  236. end;
  237. procedure delline;
  238. {Deletes the line at the cursor.}
  239. var row,left,right,bot:longint;
  240. fil:word;
  241. begin
  242. row:=whereY;
  243. left:=lo(windmin)+1;
  244. right:=lo(windmax)+1;
  245. bot:=hi(windmax)+1;
  246. fil:=$20 or (textattr shl 8);
  247. scroll_up(row+1,left,bot,right,1,fil);
  248. end;
  249. procedure insline;
  250. {Inserts a line at the cursor position.}
  251. var row,left,right,bot:longint;
  252. fil:word;
  253. begin
  254. row:=whereY;
  255. left:=lo(windmin)+1;
  256. right:=lo(windmax)+1;
  257. bot:=hi(windmax);
  258. fil:=$20 or (textattr shl 8);
  259. scroll_dn(row,left,bot-1,right,1,fil);
  260. end;
  261. procedure textmode(mode:integer);
  262. { Use this procedure to set-up a specific text-mode.}
  263. begin
  264. textattr:=$07;
  265. lastmode:=mode;
  266. mode:=mode and $ff;
  267. setscreenmode(mode);
  268. windmin:=0;
  269. windmax:=(maxcols-1) or ((maxrows-1) shl 8);
  270. clrscr;
  271. end;
  272. procedure textcolor(colour:byte);
  273. {All text written after calling this will have color as foreground colour.}
  274. begin
  275. textattr:=(textattr and $70) or (colour and $f)+colour and 128;
  276. end;
  277. procedure textbackground(colour:byte);
  278. {All text written after calling this will have colour as background colour.}
  279. begin
  280. textattr:=(textattr and $8f) or ((colour and $7) shl 4);
  281. end;
  282. procedure normvideo;
  283. {Changes the text-background to black and the foreground to white.}
  284. begin
  285. textattr:=$7;
  286. end;
  287. procedure lowvideo;
  288. {All text written after this will have low intensity.}
  289. begin
  290. textattr:=textattr and $f7;
  291. end;
  292. procedure highvideo;
  293. {All text written after this will have high intensity.}
  294. begin
  295. textattr:=textattr or $8;
  296. end;
  297. procedure delay(ms:word);
  298. {Waits ms microseconds.}
  299. begin
  300. dossleep(ms)
  301. end;
  302. procedure window(left,top,right,bottom:byte);
  303. {Change the write window to the given coordinates.}
  304. begin
  305. if (left<1) or
  306. (top<1) or
  307. (right>maxcols) or
  308. (bottom>maxrows) or
  309. (left>right) or
  310. (top>bottom) then
  311. exit;
  312. windmin:=(left-1) or ((top-1) shl 8);
  313. windmax:=(right-1) or ((bottom-1) shl 8);
  314. gotoXY(1,1);
  315. end;
  316. procedure writePchar(s:Pchar;len:word);
  317. {Write a series of characters to the screen.
  318. Not very fast, but is just text-mode isn't it?}
  319. var
  320. x,y:word;
  321. i,n:integer;
  322. screl:word;
  323. ca:Pchar;
  324. begin
  325. i:=0;
  326. getcursor(y,x);
  327. while i<=len-1 do
  328. begin
  329. case s[i] of
  330. #8: x:=x-1;
  331. #9: x:=(x-lo(windmin)) and $fff8+8+lo(windmin);
  332. #10: ;
  333. #13: begin
  334. x:=lo(windmin);
  335. inc(y);
  336. end;
  337. else
  338. begin
  339. ca:=@s[i];
  340. n:=1;
  341. while not(s[i+1] in [#8,#9,#10,#13]) and
  342. (x+n<=lo(windmax)) and (i<len-1) do
  343. begin
  344. inc(n);
  345. inc(i);
  346. end;
  347. viowrtcharstratt(ca,n,y,x,textattr,0);
  348. x:=x+n;
  349. end;
  350. end;
  351. if x>lo(windmax) then
  352. begin
  353. x:=lo(windmin);
  354. inc(y);
  355. end;
  356. if y>hi(windmax) then
  357. begin
  358. screl:=$20+textattr shl 8;
  359. scroll_up(hi(windmin),lo(windmin),
  360. hi(windmax),lo(windmax),
  361. 1,screl);
  362. y:=hi(windmax);
  363. end;
  364. inc(i);
  365. end;
  366. setcursor(y,x);
  367. end;
  368. function crtread(var f:textrec):word;
  369. {Read a series of characters from the console.}
  370. var max,curpos:integer;
  371. c:char;
  372. clist:array[0..2] of char;
  373. begin
  374. max:=f.bufsize-2;
  375. curpos:=0;
  376. repeat
  377. c:=readkey;
  378. case c of
  379. #0:
  380. readkey;
  381. #8:
  382. if curpos>0 then
  383. begin
  384. clist:=#8' '#8;
  385. writePchar(@clist,3);
  386. dec(curpos);
  387. end;
  388. #13:
  389. begin
  390. f.bufptr^[curpos]:=#13;
  391. inc(curpos);
  392. f.bufptr^[curpos]:=#10;
  393. inc(curpos);
  394. f.bufpos:=0;
  395. f.bufend:=curpos;
  396. clist[0]:=#13;
  397. writePchar(@clist,1);
  398. break;
  399. end;
  400. #32..#255:
  401. if curpos<max then
  402. begin
  403. f.bufptr^[curpos]:=c;
  404. inc(curpos);
  405. writePchar(@c,1);
  406. end;
  407. end;
  408. until false;
  409. crtread:=0;
  410. end;
  411. function crtwrite(var f:textrec):word;
  412. {Write a series of characters to the console.}
  413. begin
  414. writePchar(Pchar(f.bufptr),f.bufpos);
  415. f.bufpos:=0;
  416. crtwrite:=0;
  417. end;
  418. function crtopen(var f:textrec):integer;
  419. begin
  420. if f.mode=fmoutput then
  421. crtopen:=0
  422. else
  423. crtopen:=5;
  424. end;
  425. function crtinout(var f:textrec):integer;
  426. begin
  427. case f.mode of
  428. fminput:
  429. crtinout:=crtread(f);
  430. fmoutput:
  431. crtinout:=crtwrite(f);
  432. end;
  433. end;
  434. function crtclose(var f:textrec):integer;
  435. begin
  436. f.mode:=fmclosed;
  437. crtclose:=0;
  438. end;
  439. procedure assigncrt(var f:text);
  440. {Assigns a file to the crt console.}
  441. begin
  442. textrec(f).mode:=fmclosed;
  443. textrec(f).bufsize:=128;
  444. textrec(f).bufptr:=@textrec(f).buffer;
  445. textrec(f).bufpos:=0;
  446. textrec(f).openfunc:=@crtopen;
  447. textrec(f).inoutfunc:=@crtinout;
  448. textrec(f).flushfunc:=@crtinout;
  449. textrec(f).closefunc:=@crtclose;
  450. textrec(f).name[0]:='.';
  451. textrec(f).name[0]:=#0;
  452. end;
  453. procedure sound(hz:word);
  454. {sound and nosound are not implemented because the OS/2 API supports a freq/
  455. duration procedure instead of start/stop procedures.}
  456. begin
  457. end;
  458. procedure nosound;
  459. begin
  460. end;
  461. {Initialization.}
  462. var
  463. curmode: viomodeinfo;
  464. begin
  465. textattr:=lightgray;
  466. curmode.cb:=sizeof(curmode);
  467. viogetmode(curmode,0);
  468. maxcols:=curmode.col;
  469. maxrows:=curmode.row;
  470. lastmode:=0;
  471. case maxcols of
  472. 40: lastmode:=0;
  473. 80: lastmode:=1;
  474. 132: lastmode:=2;
  475. end;
  476. case maxrows of
  477. 25:;
  478. 28: lastmode:=lastmode+16;
  479. 43: lastmode:=lastmode+32;
  480. 50: lastmode:=lastmode+48;
  481. end;
  482. windmin:=0;
  483. windmax:=((maxrows-1) shl 8) or (maxcols-1);
  484. crt_error:=cenoerror;
  485. assigncrt(input);
  486. textrec(input).mode:=fminput;
  487. assigncrt(output);
  488. textrec(output).mode:=fmoutput;
  489. end.
  490. {
  491. $Log$
  492. Revision 1.5 2003-10-18 16:53:21 hajny
  493. * longint2cardinal
  494. Revision 1.4 2003/09/24 12:30:08 yuri
  495. * Removed emx code from crt.pas
  496. - Removed doscalls.imp (not full and obsolete)
  497. Revision 1.3 2002/08/04 19:37:55 hajny
  498. * fix for bug 1998 (write in window) + removed warnings
  499. }