crt.pas 15 KB

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