crt.pp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1998 by Nils Sjoholm
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit Crt;
  12. Interface
  13. Const
  14. { Controlling consts }
  15. Flushing=false; {if true then don't buffer output}
  16. ScreenWidth = 80;
  17. ScreenHeight = 25;
  18. { CRT modes }
  19. BW40 = 0; { 40x25 B/W on Color Adapter }
  20. CO40 = 1; { 40x25 Color on Color Adapter }
  21. BW80 = 2; { 80x25 B/W on Color Adapter }
  22. CO80 = 3; { 80x25 Color on Color Adapter }
  23. Mono = 7; { 80x25 on Monochrome Adapter }
  24. Font8x8 = 256; { Add-in for ROM font }
  25. { Mode constants for 3.0 compatibility }
  26. C40 = CO40;
  27. C80 = CO80;
  28. {
  29. When using this color constants on the Amiga
  30. you can bet that they don't work as expected.
  31. You never know what color the user has on
  32. his Amiga. Perhaps we should do a check of
  33. the number of bitplanes (for number of colors)
  34. The normal 4 first pens for an Amiga are
  35. 0 LightGrey
  36. 1 Black
  37. 2 White
  38. 3 Blue
  39. }
  40. { Foreground and background color constants }
  41. Black = 1; { normal pen for amiga }
  42. Blue = 3; { windowborder color }
  43. Green = 15;
  44. Cyan = 7;
  45. Red = 4;
  46. Magenta = 5;
  47. Brown = 6;
  48. LightGray = 0; { canvas color }
  49. { Foreground color constants }
  50. DarkGray = 8;
  51. LightBlue = 9;
  52. LightGreen = 10;
  53. LightCyan = 11;
  54. LightRed = 12;
  55. LightMagenta = 13;
  56. Yellow = 14;
  57. White = 2; { third color on amiga }
  58. { Add-in for blinking }
  59. Blink = 128;
  60. {Other Defaults}
  61. TextAttr : Byte = $07;
  62. LastMode : Word = 3;
  63. WindMin : Word = $0;
  64. WindMax : Word = $184f;
  65. var
  66. { CheckBreak have to make this one to a function for Amiga }
  67. CheckEOF,
  68. CheckSnow,
  69. DirectVideo: Boolean;
  70. Procedure AssignCrt(Var F: Text);
  71. Function KeyPressed: Boolean;
  72. Function ReadKey: Char;
  73. Procedure TextMode(Mode: Integer);
  74. Procedure Window(X1, Y1, X2, Y2: Integer);
  75. Procedure GoToXy(X: Integer; Y: Integer);
  76. Function WhereX: Integer;
  77. Function WhereY: Integer;
  78. Procedure ClrScr;
  79. Procedure ClrEol;
  80. Procedure InsLine;
  81. Procedure DelLine;
  82. Procedure TextColor(Color: Byte);
  83. Procedure TextBackground(Color: Byte);
  84. Procedure LowVideo;
  85. Procedure HighVideo;
  86. Procedure NormVideo;
  87. Procedure Delay(DTime: Word);
  88. Procedure Sound(Hz: Word);
  89. Procedure NoSound;
  90. { Extra functions }
  91. Procedure CursorOn;
  92. Procedure CursorOff;
  93. Function CheckBreak: Boolean;
  94. Implementation
  95. {
  96. The definitions of TextRec and FileRec are in separate files.
  97. }
  98. {$i textrec.inc}
  99. {$i filerec.inc}
  100. Type
  101. pInfoData = ^tInfoData;
  102. tInfoData = packed record
  103. id_NumSoftErrors : Longint; { number of soft errors on disk }
  104. id_UnitNumber : Longint; { Which unit disk is (was) mounted on }
  105. id_DiskState : Longint; { See defines below }
  106. id_NumBlocks : Longint; { Number of blocks on disk }
  107. id_NumBlocksUsed : Longint; { Number of block in use }
  108. id_BytesPerBlock : Longint;
  109. id_DiskType : Longint; { Disk Type code }
  110. id_VolumeNode : Longint; { BCPL pointer to volume node }
  111. id_InUse : Longint; { Flag, zero if not in use }
  112. end;
  113. { * List Node Structure. Each member in a list starts with a Node * }
  114. pNode = ^tNode;
  115. tNode = packed Record
  116. ln_Succ, { * Pointer to next (successor) * }
  117. ln_Pred : pNode; { * Pointer to previous (predecessor) * }
  118. ln_Type : Byte;
  119. ln_Pri : Shortint; { * Priority, for sorting * }
  120. ln_Name : PChar; { * ID string, null terminated * }
  121. End; { * Note: Integer aligned * }
  122. { normal, full featured list }
  123. pList = ^tList;
  124. tList = packed record
  125. lh_Head : pNode;
  126. lh_Tail : pNode;
  127. lh_TailPred : pNode;
  128. lh_Type : Byte;
  129. l_pad : Byte;
  130. end;
  131. pMsgPort = ^tMsgPort;
  132. tMsgPort = packed record
  133. mp_Node : tNode;
  134. mp_Flags : Byte;
  135. mp_SigBit : Byte; { signal bit number }
  136. mp_SigTask : Pointer; { task to be signalled (TaskPtr) }
  137. mp_MsgList : tList; { message linked list }
  138. end;
  139. pMessage = ^tMessage;
  140. tMessage = packed record
  141. mn_Node : tNode;
  142. mn_ReplyPort : pMsgPort; { message reply port }
  143. mn_Length : Word; { message len in bytes }
  144. end;
  145. pIOStdReq = ^tIOStdReq;
  146. tIOStdReq = packed record
  147. io_Message : tMessage;
  148. io_Device : Pointer; { device node pointer }
  149. io_Unit : Pointer; { unit (driver private)}
  150. io_Command : Word; { device command }
  151. io_Flags : Byte;
  152. io_Error : Shortint; { error or warning num }
  153. io_Actual : Longint; { actual number of bytes transferred }
  154. io_Length : Longint; { requested number bytes transferred}
  155. io_Data : Pointer; { points to data area }
  156. io_Offset : Longint; { offset for block structured devices }
  157. end;
  158. pIntuiMessage = ^tIntuiMessage;
  159. tIntuiMessage = packed record
  160. ExecMessage : tMessage;
  161. Class_ : Longint;
  162. Code : Word;
  163. Qualifier : Word;
  164. IAddress : Pointer;
  165. MouseX,
  166. MouseY : Word;
  167. Seconds,
  168. Micros : Longint;
  169. IDCMPWindow : Pointer;
  170. SpecialLink : pIntuiMessage;
  171. end;
  172. pWindow = ^tWindow;
  173. tWindow = packed record
  174. NextWindow : pWindow; { for the linked list in a screen }
  175. LeftEdge,
  176. TopEdge : Integer; { screen dimensions of window }
  177. Width,
  178. Height : Integer; { screen dimensions of window }
  179. MouseY,
  180. MouseX : Integer; { relative to upper-left of window }
  181. MinWidth,
  182. MinHeight : Integer; { minimum sizes }
  183. MaxWidth,
  184. MaxHeight : Word; { maximum sizes }
  185. Flags : Longint; { see below for defines }
  186. MenuStrip : Pointer; { the strip of Menu headers }
  187. Title : PChar; { the title text for this window }
  188. FirstRequest : Pointer; { all active Requesters }
  189. DMRequest : Pointer; { double-click Requester }
  190. ReqCount : Integer; { count of reqs blocking Window }
  191. WScreen : Pointer; { this Window's Screen }
  192. RPort : Pointer; { this Window's very own RastPort }
  193. BorderLeft,
  194. BorderTop,
  195. BorderRight,
  196. BorderBottom : Shortint;
  197. BorderRPort : Pointer;
  198. FirstGadget : Pointer;
  199. Parent,
  200. Descendant : pWindow;
  201. Pointer_ : Pointer; { sprite data }
  202. PtrHeight : Shortint; { sprite height (not including sprite padding) }
  203. PtrWidth : Shortint; { sprite width (must be less than or equal to 16) }
  204. XOffset,
  205. YOffset : Shortint; { sprite offsets }
  206. IDCMPFlags : Longint; { User-selected flags }
  207. UserPort,
  208. WindowPort : pMsgPort;
  209. MessageKey : pIntuiMessage;
  210. DetailPen,
  211. BlockPen : Byte; { for bar/border/gadget rendering }
  212. CheckMark : Pointer;
  213. ScreenTitle : PChar; { if non-null, Screen title when Window is active }
  214. GZZMouseX : Integer;
  215. GZZMouseY : Integer;
  216. GZZWidth : Integer;
  217. GZZHeight : Word;
  218. ExtData : Pointer;
  219. UserData : Pointer; { general-purpose pointer to User data extension }
  220. WLayer : Pointer;
  221. IFont : Pointer;
  222. MoreFlags : Longint;
  223. end;
  224. pConUnit = ^tConUnit;
  225. tConUnit = packed record
  226. cu_MP : tMsgPort;
  227. cu_Window : Pointer; { (WindowPtr) intuition window bound to this unit }
  228. cu_XCP : Integer; { character position }
  229. cu_YCP : Integer;
  230. cu_XMax : Integer; { max character position }
  231. cu_YMax : Integer;
  232. cu_XRSize : Integer; { character raster size }
  233. cu_YRSize : Integer;
  234. cu_XROrigin : Integer; { raster origin }
  235. cu_YROrigin : Integer;
  236. cu_XRExtant : Integer; { raster maxima }
  237. cu_YRExtant : Integer;
  238. cu_XMinShrink : Integer; { smallest area intact from resize process }
  239. cu_YMinShrink : Integer;
  240. cu_XCCP : Integer; { cursor position }
  241. cu_YCCP : Integer;
  242. cu_KeyMapStruct : Pointer;
  243. cu_TabStops : Array [0..80-1] of Word;
  244. cu_Mask : Shortint;
  245. cu_FgPen : Shortint;
  246. cu_BgPen : Shortint;
  247. cu_AOLPen : Shortint;
  248. cu_DrawMode : Shortint;
  249. cu_AreaPtSz : Shortint;
  250. cu_AreaPtrn : Pointer; { cursor area pattern }
  251. cu_Minterms : Array [0..7] of Byte; { console minterms }
  252. cu_Font : Pointer; { (TextFontPtr) }
  253. cu_AlgoStyle : Byte;
  254. cu_TxFlags : Byte;
  255. cu_TxHeight : Word;
  256. cu_TxWidth : Word;
  257. cu_TxBaseline : Word;
  258. cu_TxSpacing : Word;
  259. cu_Modes : Array [0..(22+7) div 8 - 1] of Byte;
  260. cu_RawEvents : Array [0..($15+7) div 8 - 1] of Byte;
  261. end;
  262. const
  263. CD_CURRX = 1;
  264. CD_CURRY = 2;
  265. CD_MAXX = 3;
  266. CD_MAXY = 4;
  267. CSI = chr($9b);
  268. SIGBREAKF_CTRL_C = 4096;
  269. function AllocVec( size, reqm : Longint ): Pointer;
  270. begin
  271. asm
  272. MOVE.L A6,-(A7)
  273. MOVE.L size,d0
  274. MOVE.L reqm,d1
  275. MOVE.L _ExecBase, A6
  276. JSR -684(A6)
  277. MOVE.L (A7)+,A6
  278. MOVE.L d0,@RESULT
  279. end;
  280. end;
  281. function DoPkt(ID : pMsgPort;
  282. Action, Param1, Param2,
  283. Param3, Param4, Param5 : Longint) : Longint;
  284. begin
  285. asm
  286. MOVEM.L d2/d3/d4/d5/d6/d7/a6,-(A7)
  287. MOVE.L ID,d1
  288. MOVE.L Action,d2
  289. MOVE.L Param1,d3
  290. MOVE.L Param2,d4
  291. MOVE.L Param3,d5
  292. MOVE.L Param4,d6
  293. MOVE.L Param5,d7
  294. MOVE.L _DOSBase,A6
  295. JSR -240(A6)
  296. MOVEM.L (A7)+,d2/d3/d4/d5/d6/d7/a6
  297. MOVE.L d0,@RESULT
  298. end;
  299. end;
  300. procedure FreeVec( memory : Pointer );
  301. begin
  302. asm
  303. MOVE.L A6,-(A7)
  304. MOVE.L memory,a1
  305. MOVE.L _ExecBase,A6
  306. JSR -690(A6)
  307. MOVE.L (A7)+,A6
  308. end;
  309. end;
  310. function GetConsoleTask : pMsgPort;
  311. begin
  312. asm
  313. MOVE.L A6,-(A7)
  314. MOVE.L _DOSBase,A6
  315. JSR -510(A6)
  316. MOVE.L (A7)+,A6
  317. MOVE.L d0,@RESULT
  318. end;
  319. end;
  320. function GetMsg(port : pMsgPort): pMessage;
  321. begin
  322. asm
  323. MOVE.L A6,-(A7)
  324. MOVE.L port,a0
  325. MOVE.L _ExecBase,A6
  326. JSR -372(A6)
  327. MOVE.L (A7)+,A6
  328. MOVE.L d0,@RESULT
  329. end;
  330. end;
  331. function ModifyIDCMP(window : pWindow;
  332. IDCMPFlags : Longint) : Boolean;
  333. begin
  334. asm
  335. MOVE.L A6,-(A7)
  336. MOVE.L window,a0
  337. MOVE.L IDCMPFlags,d0
  338. MOVE.L _IntuitionBase,A6
  339. JSR -150(A6)
  340. MOVE.L (A7)+,A6
  341. TST.L d0
  342. bne @success
  343. bra @end
  344. @success:
  345. move.b #1,d0
  346. @end:
  347. move.b d0,@RESULT
  348. end;
  349. end;
  350. procedure ReplyMsg(mess : pMessage);
  351. begin
  352. asm
  353. MOVE.L A6,-(A7)
  354. MOVE.L mess,a1
  355. MOVE.L _ExecBase,A6
  356. JSR -378(A6)
  357. MOVE.L (A7)+,A6
  358. end;
  359. end;
  360. function WaitPort(port : pMsgPort): pMessage;
  361. begin
  362. asm
  363. MOVE.L A6,-(A7)
  364. MOVE.L port,a0
  365. MOVE.L _ExecBase,A6
  366. JSR -384(A6)
  367. MOVE.L (A7)+,A6
  368. MOVE.L d0,@RESULT
  369. end;
  370. end;
  371. procedure Delay_(ticks : Longint);
  372. begin
  373. asm
  374. MOVE.L A6,-(A7)
  375. MOVE.L ticks,d1
  376. MOVE.L _DOSBase,A6
  377. JSR -198(A6)
  378. MOVE.L (A7)+,A6
  379. end;
  380. end;
  381. function SetSignal(newSignals, signalMask : Longint) : Longint;
  382. begin
  383. asm
  384. MOVE.L A6,-(A7)
  385. MOVE.L newSignals,d0
  386. MOVE.L signalMask,d1
  387. MOVE.L _ExecBase,A6
  388. JSR -306(A6)
  389. MOVE.L (A7)+,A6
  390. MOVE.L d0,@RESULT
  391. end;
  392. end;
  393. function OpenInfo : pInfoData;
  394. var
  395. port : pMsgPort;
  396. info : pInfoData;
  397. bptr, d4, d5, d6, d7 : Longint;
  398. begin
  399. info := pInfoData(AllocVec(SizeOf(tInfoData), 1));
  400. if info <> nil then begin
  401. port := GetConsoleTask;
  402. bptr := Longint(info) shr 2;
  403. if port <> nil then begin
  404. if DoPkt(port, $19, bptr, d4, d5, d6, d7) <> 0 then info := pInfoData(bptr shl 2)
  405. else port := nil;
  406. end;
  407. if port = nil then begin
  408. FreeVec(info);
  409. info := nil;
  410. end;
  411. end;
  412. OpenInfo := info;
  413. end;
  414. procedure CloseInfo(var info : pInfoData);
  415. begin
  416. if info <> nil then begin
  417. FreeVec(info);
  418. info := nil;
  419. end;
  420. end;
  421. function ConData(modus : byte) : integer;
  422. var
  423. info : pInfoData;
  424. theunit : pConUnit;
  425. pos : Longint;
  426. begin
  427. pos := 1;
  428. info := OpenInfo;
  429. if info <> nil then begin
  430. theunit := pConUnit((pIoStdReq(info^.id_InUse))^.io_Unit);
  431. case modus of
  432. CD_CURRX : pos := theunit^.cu_XCP;
  433. CD_CURRY : pos := theunit^.cu_YCP;
  434. CD_MAXX : pos := theunit^.cu_XMax;
  435. CD_MAXY : pos := theunit^.cu_YMax;
  436. end;
  437. CloseInfo(info);
  438. end;
  439. ConData := pos + 1;
  440. end;
  441. function WhereX : integer;
  442. begin
  443. WhereX := ConData(CD_CURRX);
  444. end;
  445. function WhereY : integer;
  446. begin
  447. WhereY := ConData(CD_CURRY);
  448. end;
  449. function maxx : integer;
  450. begin
  451. maxx := ConData(CD_MAXX);
  452. end;
  453. function maxy : integer;
  454. begin
  455. maxy := ConData(CD_MAXY);
  456. end;
  457. procedure GotoXY(x, y : integer);
  458. var
  459. mx, my : integer;
  460. begin
  461. mx := maxx;
  462. my := maxy;
  463. if x < 1 then x := wherex
  464. else if x > mx then x := mx;
  465. if y < 1 then y := wherey
  466. else if y > my then y := my;
  467. Write(CSI, y, ';', x, 'H');
  468. end;
  469. procedure CursorOff;
  470. begin
  471. Write(CSI,'0 p');
  472. end;
  473. procedure CursorOn;
  474. begin
  475. Write(CSI,'1 p');
  476. end;
  477. procedure ClrScr;
  478. begin
  479. Write(Chr($0c));
  480. end;
  481. function ReadKey : char;
  482. const
  483. IDCMP_VANILLAKEY = $00200000;
  484. IDCMP_RAWKEY = $00000400;
  485. var
  486. info : pInfoData;
  487. win : pWindow;
  488. imsg : pIntuiMessage;
  489. msg : pMessage;
  490. key : char;
  491. idcmp, vanil : Longint;
  492. begin
  493. key := #0;
  494. info := OpenInfo;
  495. if info <> nil then begin
  496. win := pWindow(pConUnit((pIoStdReq(info^.id_InUse))^.io_Unit)^.cu_Window);
  497. idcmp := win^.IDCMPFlags;
  498. vanil := IDCMP_VANILLAKEY or IDCMP_RAWKEY;
  499. ModifyIDCMP(win, (idcmp or vanil));
  500. repeat
  501. msg := WaitPort(win^.UserPort);
  502. imsg := pIntuiMessage(GetMsg(win^.UserPort));
  503. if (imsg^.Class_ = IDCMP_VANILLAKEY) or (imsg^.Class_ = IDCMP_RAWKEY) then key := char(imsg^.Code);
  504. ReplyMsg(pMessage(imsg));
  505. until key <> #0;
  506. repeat
  507. msg := GetMsg(win^.UserPort);
  508. if msg <> nil then ReplyMsg(msg);
  509. until msg = nil;
  510. ModifyIDCMP(win, idcmp);
  511. CloseInfo(info);
  512. end;
  513. ReadKey := key;
  514. end;
  515. function KeyPressed : Boolean;
  516. const
  517. IDCMP_VANILLAKEY = $00200000;
  518. IDCMP_RAWKEY = $00000400;
  519. var
  520. info : pInfoData;
  521. win : pWindow;
  522. imsg : pIntuiMessage;
  523. msg : pMessage;
  524. idcmp, vanil : Longint;
  525. ispressed : Boolean;
  526. begin
  527. ispressed := False;
  528. info := OpenInfo;
  529. if info <> nil then begin
  530. win := pWindow(pConUnit((pIoStdReq(info^.id_InUse))^.io_Unit)^.cu_Window);
  531. idcmp := win^.IDCMPFlags;
  532. vanil := IDCMP_VANILLAKEY or IDCMP_RAWKEY;
  533. ModifyIDCMP(win, (idcmp or vanil));
  534. msg := WaitPort(win^.UserPort);
  535. imsg := pIntuiMessage(GetMsg(win^.UserPort));
  536. if (imsg^.Class_ = IDCMP_VANILLAKEY) or (imsg^.Class_ = IDCMP_RAWKEY) then ispressed := true;
  537. ReplyMsg(pMessage(imsg));
  538. repeat
  539. msg := GetMsg(win^.UserPort);
  540. if msg <> nil then ReplyMsg(msg);
  541. until msg = nil;
  542. ModifyIDCMP(win, idcmp);
  543. CloseInfo(info);
  544. end;
  545. KeyPressed := ispressed;
  546. end;
  547. procedure TextColor(color : byte);
  548. begin
  549. Write(CSI, '3', color, 'm');
  550. end;
  551. procedure TextBackground(color : byte);
  552. begin
  553. Write(CSI, '4', color, 'm');
  554. end;
  555. procedure window(X1,Y1,X2,Y2 : Integer);
  556. begin
  557. end;
  558. procedure assigncrt(var f : text);
  559. begin
  560. end;
  561. procedure DelLine;
  562. begin
  563. Write(CSI,'X');
  564. end;
  565. procedure ClrEol;
  566. begin
  567. Write(CSI,'K');
  568. end;
  569. procedure InsLine;
  570. begin
  571. Write(CSI,'1 L');
  572. end;
  573. procedure cursorbig;
  574. begin
  575. end;
  576. procedure lowvideo;
  577. begin
  578. end;
  579. procedure highvideo;
  580. begin
  581. end;
  582. procedure nosound;
  583. begin
  584. end;
  585. procedure sound(hz : word);
  586. begin
  587. end;
  588. procedure delay(DTime : Word);
  589. var
  590. dummy : Longint;
  591. begin
  592. dummy := trunc((real(DTime) / 1000.0) * 50.0);
  593. Delay_(dummy);
  594. end;
  595. function CheckBreak : boolean;
  596. begin
  597. if (SetSignal(0, 0) and SIGBREAKF_CTRL_C) = SIGBREAKF_CTRL_C then
  598. CheckBreak := true
  599. else
  600. CheckBreak := false;
  601. end;
  602. procedure textmode(mode : integer);
  603. begin
  604. end;
  605. procedure normvideo;
  606. begin
  607. end;
  608. end.