video.inc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. {
  2. System independent low-level video interface for OS/2
  3. $Id$
  4. }
  5. uses
  6. {$IFDEF PPC_FPC}
  7. DosCalls, VioCalls;
  8. {$ELSE}
  9. {$IFDEF PPC_VIRTUAL}
  10. Os2Base;
  11. {$ENDIF}
  12. {$ENDIF}
  13. {$IFNDEF FPC}
  14. type
  15. cardinal = longint;
  16. {$ENDIF}
  17. const
  18. InitVideoCalled: boolean = false;
  19. LastCursorType: word = crUnderline;
  20. EmptyCell: cardinal = $0720;
  21. OrigScreen: PVideoBuf = nil;
  22. OrigScreenSize: cardinal = 0;
  23. {$IFDEF PPC_VIRTUAL}
  24. type
  25. TVioCursorInfo = VioCursorInfo;
  26. TVioModeInfo = VioModeInfo;
  27. TVioIntensity = VioIntensity;
  28. {$ENDIF}
  29. var OrigCurType: TVioCursorInfo;
  30. OrigVioMode: TVioModeInfo;
  31. OrigHighBit: TVioIntensity;
  32. OrigCurRow: word;
  33. OrigCurCol: word;
  34. CellHeight: byte;
  35. procedure TargetEntry;
  36. var P: PVideoModeList;
  37. PScr: pointer;
  38. begin
  39. {Remember original video mode, cursor type and high bit behaviour setting}
  40. OrigVioMode.cb := SizeOf (OrigVioMode);
  41. VioGetMode (OrigVioMode, 0);
  42. VioGetCurType (OrigCurType, 0);
  43. VioGetCurPos (OrigCurRow, OrigCurCol, 0);
  44. with OrigHighBit do
  45. begin
  46. cb := 6;
  47. rType := 2;
  48. end;
  49. VioGetState (OrigHighBit, 0);
  50. {Register the curent video mode in Modes if not there yet}
  51. with OrigVioMode do
  52. begin
  53. P := Modes;
  54. while (P <> nil) and ((P^.Row <> Row) or (P^.Col <> Col)
  55. or (P^.Color <> (Color >= Colors_16))) do
  56. P := P^.Next;
  57. if P = nil then
  58. {Assume we have at least 16 colours available in "colour" modes}
  59. RegisterVideoMode (Col, Row, Color >= Colors_16,
  60. {$IFDEF FPC}
  61. @DefaultVideoModeSelector, 0);
  62. {$ELSE}
  63. DefaultVideoModeSelector, 0);
  64. {$ENDIF}
  65. end;
  66. {Get the address of the original videobuffer and size.}
  67. if VioGetBuf (PScr, PWord (@OrigScreenSize)^, 0) = 0 then
  68. begin
  69. {$IFDEF PPC_VIRTUAL}
  70. SelToFlat (PScr);
  71. {$ELSE}
  72. PScr := SelToFlat (TFarPtr (PScr));
  73. {$ENDIF}
  74. GetMem (OrigScreen, OrigScreenSize);
  75. Move (PScr^, OrigScreen^, OrigScreenSize);
  76. end;
  77. end;
  78. procedure TargetExit;
  79. begin
  80. end;
  81. procedure CheckCellHeight;
  82. var OldCD, CD: TVioCursorInfo;
  83. begin
  84. VioGetCurType (OldCD, 0);
  85. Move (OldCD, CD, SizeOf (CD));
  86. with CD do
  87. begin
  88. Attr := 0;
  89. yStart := word (-90);
  90. cEnd := word (-100);
  91. end;
  92. VioSetCurType (CD, 0);
  93. VioGetCurType (CD, 0);
  94. CellHeight := CD.cEnd;
  95. VioSetCurType (OldCD, 0);
  96. end;
  97. procedure RegisterVideoModes;
  98. begin
  99. { BW modes are rejected on my (colour) configuration. I can't imagine
  100. OS/2 running on MCGA anyway... ;-)
  101. RegisterVideoMode (40, 25, False, @DefaultVideoModeSelector, 0);
  102. RegisterVideoMode (80, 25, False, @DefaultVideoModeSelector, 0);
  103. }
  104. {$IFDEF FPC}
  105. RegisterVideoMode (40, 25, True, @DefaultVideoModeSelector, 0);
  106. RegisterVideoMode (80, 25, True, @DefaultVideoModeSelector, 0);
  107. RegisterVideoMode (80, 30, True, @DefaultVideoModeSelector, 0);
  108. RegisterVideoMode (80, 43, True, @DefaultVideoModeSelector, 0);
  109. RegisterVideoMode (80, 50, True, @DefaultVideoModeSelector, 0);
  110. {$ELSE}
  111. RegisterVideoMode (40, 25, True, DefaultVideoModeSelector, 0);
  112. RegisterVideoMode (80, 25, True, DefaultVideoModeSelector, 0);
  113. RegisterVideoMode (80, 30, True, DefaultVideoModeSelector, 0);
  114. RegisterVideoMode (80, 43, True, DefaultVideoModeSelector, 0);
  115. RegisterVideoMode (80, 50, True, DefaultVideoModeSelector, 0);
  116. {$ENDIF}
  117. { The following modes wouldn't work on plain VGA; is it useful to check
  118. for their availability on the program startup?
  119. RegisterVideoMode (132, 25, True, @DefaultVideoModeSelector, 0);
  120. RegisterVideoMode (132, 30, True, @DefaultVideoModeSelector, 0);
  121. RegisterVideoMode (132, 43, True, @DefaultVideoModeSelector, 0);
  122. RegisterVideoMode (132, 50, True, @DefaultVideoModeSelector, 0);
  123. }
  124. end;
  125. procedure SetHighBitBlink (Blink: boolean);
  126. var VI: TVioIntensity;
  127. begin
  128. with VI do
  129. begin
  130. cb := 6;
  131. rType := 2;
  132. fs := byte (not (Blink));
  133. end;
  134. VioSetState (VI, 0);
  135. end;
  136. procedure InitVideo;
  137. var MI: TVioModeInfo;
  138. begin
  139. InitVideoCalled := true;
  140. VideoBufSize := 0;
  141. MI.cb := SizeOf (MI);
  142. VioGetMode (MI, 0);
  143. with MI do
  144. begin
  145. ScreenWidth := Col;
  146. ScreenHeight := Row;
  147. ScreenColor := Color >= Colors_16;
  148. end;
  149. VioGetCurPos (CursorY, CursorX, 0);
  150. LowAscii := true;
  151. SetCursorType (LastCursorType);
  152. {Get the address of the videobuffer.}
  153. {$IFDEF PPC_VIRTUAL}
  154. if VioGetBuf (pointer (VideoBuf), PWord (@VideoBufSize)^, 0) = 0 then
  155. begin
  156. SelToFlat (pointer (VideoBuf));
  157. {$ELSE}
  158. if VioGetBuf (VideoBuf, PWord (@VideoBufSize)^, 0) = 0 then
  159. begin
  160. VideoBuf := SelToFlat (TFarPtr (VideoBuf));
  161. {$ENDIF}
  162. SetHighBitBlink (true);
  163. end
  164. else
  165. ErrorHandler (errVioInit, nil);
  166. end;
  167. procedure SetCursorPos (NewCursorX, NewCursorY: word);
  168. begin
  169. if VioSetCurPos (NewCursorY, NewCursorX, 0) = 0 then
  170. begin
  171. CursorX := NewCursorX;
  172. CursorY := NewCursorY;
  173. end
  174. else
  175. {Do not set an error code; people should fix invalid NewCursorX
  176. or NewCursorY values when designing, there is no need for detecting
  177. these errors at runtime.}
  178. RunError (225);
  179. end;
  180. function GetCursorType: word;
  181. var CD: TVioCursorInfo;
  182. begin
  183. VioGetCurType (CD, 0); {Never fails, because handle is default handle.}
  184. with CD do
  185. begin
  186. CursorLines := Succ (cEnd) - yStart;
  187. if Attr = word (-1) then
  188. GetCursorType := crHidden
  189. else
  190. {Because the cursor's start and end lines are returned, we'll have
  191. to guess heuristically what cursor type we have.}
  192. if CursorLines = 0 then
  193. {Probably this does not occur, but you'll never know.}
  194. GetCursorType := crHidden
  195. else if CursorLines <= Succ (CellHeight div 4) then
  196. GetCursorType := crUnderline
  197. else if CursorLines <= Succ (CellHeight div 2) then
  198. GetCursorType := crHalfBlock
  199. else
  200. GetCursorType := crBlock;
  201. end;
  202. end;
  203. procedure SetCursorType (NewType: word);
  204. var CD: TVioCursorInfo;
  205. begin
  206. VioGetCurType (CD, 0);
  207. with CD do
  208. begin
  209. case NewType of
  210. crHidden: Attr := word (-1);
  211. crUnderline:
  212. begin
  213. yStart := word (-90);
  214. cEnd := word (-100);
  215. end;
  216. crHalfBlock:
  217. begin
  218. yStart := word (-50);
  219. cEnd := word (-100);
  220. end;
  221. crBlock:
  222. begin
  223. yStart := 0;
  224. cEnd := word (-100);
  225. end;
  226. end;
  227. VioSetCurType (CD, 0);
  228. VioGetCurType (CD, 0);
  229. CursorLines := Succ (cEnd) - yStart;
  230. end;
  231. end;
  232. procedure DoneVideo;
  233. var PScr: pointer;
  234. ScrSize: cardinal;
  235. begin
  236. if InitVideoCalled then
  237. begin
  238. LastCursorType := GetCursorType;
  239. ClearScreen;
  240. {Restore original settings}
  241. VioSetMode (OrigVioMode, 0);
  242. CheckCellHeight;
  243. {Set CursorX and CursorY}
  244. SetCursorPos (0, 0);
  245. VioSetState (OrigHighBit, 0);
  246. VioSetCurType (OrigCurType, 0);
  247. VioSetCurPos (OrigCurRow, OrigCurCol, 0);
  248. VideoBufSize := 0;
  249. InitVideoCalled := false;
  250. if (OrigScreenSize <> 0) and (OrigScreen <> nil) then
  251. begin
  252. ScrSize := 0;
  253. if (VioGetBuf (PScr, PWord (@ScrSize)^, 0) = 0)
  254. and (ScrSize = OrigScreenSize) then
  255. begin
  256. {$IFDEF PPC_VIRTUAL}
  257. SelToFlat (PScr);
  258. {$ELSE}
  259. PScr := SelToFlat (TFarPtr (PScr));
  260. {$ENDIF}
  261. Move (OrigScreen^, PScr^, OrigScreenSize);
  262. VioShowBuf (0, ScrSize, 0);
  263. end;
  264. end;
  265. end;
  266. end;
  267. function GetCapabilities: word;
  268. begin
  269. GetCapabilities := $3F;
  270. end;
  271. function DefaultVideoModeSelector (const VideoMode: TVideoMode; Params: longint): boolean;
  272. var OldMI, MI: TVioModeInfo;
  273. begin
  274. OldMI.cb := SizeOf (OldMI);
  275. if VioGetMode (OldMI, 0) <> 0 then
  276. DefaultVideoModeSelector := false
  277. else
  278. begin
  279. with MI do
  280. begin
  281. cb := 8;
  282. fbType := 1;
  283. if VideoMode.Color then
  284. Color := Colors_16
  285. else
  286. Color := Colors_2;
  287. Col := VideoMode.Col;
  288. Row := VideoMode.Row;
  289. end;
  290. if VioSetMode (MI, 0) = 0 then
  291. {$IFDEF PPC_VIRTUAL}
  292. if VioGetBuf (pointer (VideoBuf),
  293. PWord (@VideoBufSize)^, 0) = 0 then
  294. begin
  295. SelToFlat (pointer (VideoBuf));
  296. {$ELSE}
  297. if VioGetBuf (VideoBuf, PWord (@VideoBufSize)^, 0) = 0 then
  298. begin
  299. VideoBuf := SelToFlat (TFarPtr (VideoBuf));
  300. {$ENDIF}
  301. DefaultVideoModeSelector := true;
  302. SetHighBitBlink (true);
  303. CheckCellHeight;
  304. SetCursorType (LastCursorType);
  305. ClearScreen;
  306. end
  307. else
  308. begin
  309. DefaultVideoModeSelector := false;
  310. VioSetMode (OldMI, 0);
  311. {$IFDEF PPC_VIRTUAL}
  312. VioGetBuf (pointer (VideoBuf),
  313. PWord (@VideoBufSize)^, 0);
  314. SelToFlat (pointer (VideoBuf));
  315. {$ELSE}
  316. VioGetBuf (VideoBuf, PWord (@VideoBufSize)^, 0);
  317. VideoBuf := SelToFlat (TFarPtr (VideoBuf));
  318. {$ENDIF}
  319. SetHighBitBlink (true);
  320. CheckCellHeight;
  321. SetCursorType (LastCursorType);
  322. ClearScreen;
  323. end
  324. else
  325. begin
  326. DefaultVideoModeSelector := false;
  327. {$IFDEF PPC_VIRTUAL}
  328. VioGetBuf (pointer (VideoBuf), PWord (@VideoBufSize)^, 0);
  329. SelToFlat (pointer (VideoBuf));
  330. {$ELSE}
  331. VioGetBuf (VideoBuf, PWord (@VideoBufSize)^, 0);
  332. VideoBuf := SelToFlat (TFarPtr (VideoBuf));
  333. {$ENDIF}
  334. SetHighBitBlink (true);
  335. SetCursorType (LastCursorType);
  336. end;
  337. end;
  338. end;
  339. procedure ClearScreen;
  340. begin
  341. VioScrollDn (0, 0, word (-1), word (-1), word (-1), PWord (@EmptyCell)^, 0);
  342. end;
  343. procedure UpdateScreen (Force: boolean);
  344. begin
  345. VioShowBuf (0, VideoBufSize, 0);
  346. end;
  347. {
  348. $Log$
  349. Revision 1.6 2000-10-08 14:13:19 hajny
  350. * ClearScreen correction, screen restored on exit
  351. Revision 1.5 2000/10/04 11:53:31 pierre
  352. Add TargetEntry and TargetExit (merged)
  353. Revision 1.4 2000/09/26 18:15:29 hajny
  354. + working with VP/2 already (not FPC yet)!
  355. Revision 1.3 2000/09/24 19:53:03 hajny
  356. * OS/2 implementation almost finished, not debugged yet
  357. Revision 1.2 2000/07/13 11:32:26 michael
  358. + removed logs
  359. }