video.inc 13 KB

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