video.pp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Florian Klaempfl
  5. member of the Free Pascal development team
  6. Video unit for OS/2
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. unit Video;
  14. interface
  15. {$i videoh.inc}
  16. implementation
  17. uses
  18. DosCalls, VioCalls;
  19. {$i video.inc}
  20. const
  21. LastCursorType: word = crUnderline;
  22. EmptyCell: cardinal = $0720;
  23. OrigScreen: PVideoBuf = nil;
  24. OrigScreenSize: cardinal = 0;
  25. var OrigCurType: TVioCursorInfo;
  26. OrigVioMode: TVioModeInfo;
  27. OrigHighBit: TVioIntensity;
  28. OrigCurRow: word;
  29. OrigCurCol: word;
  30. CellHeight: byte;
  31. OldVideoBuf: PVideoBuf;
  32. procedure TargetEntry;
  33. var P: PVideoModeList;
  34. PScr: pointer;
  35. begin
  36. {Remember original video mode, cursor type and high bit behaviour setting}
  37. OrigVioMode.cb := SizeOf (OrigVioMode);
  38. VioGetMode (OrigVioMode, 0);
  39. VioGetCurType (OrigCurType, 0);
  40. VioGetCurPos (OrigCurRow, OrigCurCol, 0);
  41. with OrigHighBit do
  42. begin
  43. cb := 6;
  44. rType := 2;
  45. end;
  46. VioGetState (OrigHighBit, 0);
  47. {Register the curent video mode in Modes if not there yet}
  48. with OrigVioMode do
  49. begin
  50. P := Modes;
  51. while (P <> nil) and ((P^.Row <> Row) or (P^.Col <> Col)
  52. or (P^.Color <> (Color >= Colors_16))) do
  53. P := P^.Next;
  54. if P = nil then
  55. {Assume we have at least 16 colours available in "colour" modes}
  56. RegisterVideoMode (Col, Row, Color >= Colors_16,
  57. @DefaultVideoModeSelector, 0);
  58. end;
  59. {Get the address of the original videobuffer and size.}
  60. if VioGetBuf (PScr, PWord (@OrigScreenSize)^, 0) = 0 then
  61. begin
  62. PScr := SelToFlat (TFarPtr (PScr));
  63. GetMem (OrigScreen, OrigScreenSize);
  64. Move (PScr^, OrigScreen^, OrigScreenSize);
  65. end;
  66. end;
  67. procedure CheckCellHeight;
  68. var OldCD, CD: TVioCursorInfo;
  69. begin
  70. VioGetCurType (OldCD, 0);
  71. Move (OldCD, CD, SizeOf (CD));
  72. with CD do
  73. begin
  74. Attr := 0;
  75. yStart := word (-90);
  76. cEnd := word (-100);
  77. end;
  78. VioSetCurType (CD, 0);
  79. VioGetCurType (CD, 0);
  80. CellHeight := CD.cEnd;
  81. VioSetCurType (OldCD, 0);
  82. end;
  83. procedure RegisterVideoModes;
  84. begin
  85. { BW modes are rejected on my (colour) configuration. I can't imagine
  86. OS/2 running on MCGA anyway... ;-)
  87. RegisterVideoMode (40, 25, False, @DefaultVideoModeSelector, 0);
  88. RegisterVideoMode (80, 25, False, @DefaultVideoModeSelector, 0);
  89. }
  90. RegisterVideoMode (40, 25, True, @DefaultVideoModeSelector, 0);
  91. RegisterVideoMode (80, 25, True, @DefaultVideoModeSelector, 0);
  92. RegisterVideoMode (80, 30, True, @DefaultVideoModeSelector, 0);
  93. RegisterVideoMode (80, 43, True, @DefaultVideoModeSelector, 0);
  94. RegisterVideoMode (80, 50, True, @DefaultVideoModeSelector, 0);
  95. { The following modes wouldn't work on plain VGA; is it useful to check
  96. for their availability on the program startup?
  97. RegisterVideoMode (132, 25, True, @DefaultVideoModeSelector, 0);
  98. RegisterVideoMode (132, 30, True, @DefaultVideoModeSelector, 0);
  99. RegisterVideoMode (132, 43, True, @DefaultVideoModeSelector, 0);
  100. RegisterVideoMode (132, 50, True, @DefaultVideoModeSelector, 0);
  101. }
  102. end;
  103. procedure SetHighBitBlink (Blink: boolean);
  104. var VI: TVioIntensity;
  105. begin
  106. with VI do
  107. begin
  108. cb := 6;
  109. rType := 2;
  110. fs := byte (not (Blink));
  111. end;
  112. VioSetState (VI, 0);
  113. end;
  114. procedure SysInitVideo;
  115. var MI: TVioModeInfo;
  116. begin
  117. FreeMem (OldVideoBuf, VideoBufSize);
  118. OldVideoBuf := nil;
  119. VideoBufSize := 0;
  120. MI.cb := SizeOf (MI);
  121. VioGetMode (MI, 0);
  122. with MI do
  123. begin
  124. ScreenWidth := Col;
  125. ScreenHeight := Row;
  126. ScreenColor := Color >= Colors_16;
  127. end;
  128. VioGetCurPos (CursorY, CursorX, 0);
  129. LowAscii := true;
  130. SetCursorType (LastCursorType);
  131. { Get the address of the videobuffer.}
  132. if VioGetBuf (VideoBuf, PWord (@VideoBufSize)^, 0) = 0 then
  133. begin
  134. VideoBuf := SelToFlat (TFarPtr (VideoBuf));
  135. SetHighBitBlink (true);
  136. GetMem (OldVideoBuf, VideoBufSize);
  137. Move (VideoBuf^, OldVideoBuf^, VideoBufSize);
  138. end
  139. else
  140. ErrorHandler (errVioInit, nil);
  141. end;
  142. procedure SysSetCursorPos (NewCursorX, NewCursorY: word);
  143. begin
  144. if VioSetCurPos (NewCursorY, NewCursorX, 0) = 0 then
  145. begin
  146. CursorX := NewCursorX;
  147. CursorY := NewCursorY;
  148. end
  149. else
  150. {Do not set an error code; people should fix invalid NewCursorX
  151. or NewCursorY values when designing, there is no need for detecting
  152. these errors at runtime.}
  153. RunError (225);
  154. end;
  155. function SysGetCursorType: word;
  156. var CD: TVioCursorInfo;
  157. begin
  158. VioGetCurType (CD, 0); {Never fails, because handle is default handle.}
  159. with CD do
  160. begin
  161. CursorLines := Succ (cEnd) - yStart;
  162. if Attr = word (-1) then
  163. SysGetCursorType := crHidden
  164. else
  165. {Because the cursor's start and end lines are returned, we'll have
  166. to guess heuristically what cursor type we have.}
  167. if CursorLines = 0 then
  168. {Probably this does not occur, but you'll never know.}
  169. SysGetCursorType := crHidden
  170. else if CursorLines <= Succ (CellHeight div 4) then
  171. SysGetCursorType := crUnderline
  172. else if CursorLines <= Succ (CellHeight div 2) then
  173. SysGetCursorType := crHalfBlock
  174. else
  175. SysGetCursorType := crBlock;
  176. end;
  177. end;
  178. procedure SysSetCursorType (NewType: word);
  179. var CD: TVioCursorInfo;
  180. begin
  181. VioGetCurType (CD, 0);
  182. with CD do
  183. begin
  184. case NewType of
  185. crHidden: Attr := word (-1);
  186. crUnderline:
  187. begin
  188. Attr := 0;
  189. yStart := word (-90);
  190. cEnd := word (-100);
  191. end;
  192. crHalfBlock:
  193. begin
  194. Attr := 0;
  195. yStart := word (-50);
  196. cEnd := word (-100);
  197. end;
  198. crBlock:
  199. begin
  200. Attr := 0;
  201. yStart := 0;
  202. cEnd := word (-100);
  203. end;
  204. end;
  205. VioSetCurType (CD, 0);
  206. VioGetCurType (CD, 0);
  207. CursorLines := Succ (cEnd) - yStart;
  208. end;
  209. end;
  210. procedure SysDoneVideo;
  211. var PScr: pointer;
  212. ScrSize: cardinal;
  213. begin
  214. LastCursorType := GetCursorType;
  215. ClearScreen;
  216. {Restore original settings}
  217. VioSetMode (OrigVioMode, 0);
  218. CheckCellHeight;
  219. {Set CursorX and CursorY}
  220. SetCursorPos (0, 0);
  221. VioSetState (OrigHighBit, 0);
  222. VioSetCurType (OrigCurType, 0);
  223. VioSetCurPos (OrigCurRow, OrigCurCol, 0);
  224. FreeMem (OldVideoBuf, VideoBufSize);
  225. OldVideoBuf := nil;
  226. VideoBufSize := 0;
  227. if (OrigScreenSize <> 0) and (OrigScreen <> nil) then
  228. begin
  229. ScrSize := 0;
  230. if (VioGetBuf (PScr, PWord (@ScrSize)^, 0) = 0)
  231. and (ScrSize = OrigScreenSize) then
  232. begin
  233. PScr := SelToFlat (TFarPtr (PScr));
  234. Move (OrigScreen^, PScr^, OrigScreenSize);
  235. VioShowBuf (0, ScrSize, 0);
  236. end;
  237. end;
  238. end;
  239. function SysGetCapabilities: word;
  240. begin
  241. SysGetCapabilities := $3F;
  242. end;
  243. function DefaultVideoModeSelector (const VideoMode: TVideoMode; Params: longint): boolean;
  244. var OldMI, MI: TVioModeInfo;
  245. begin
  246. OldMI.cb := SizeOf (OldMI);
  247. if VioGetMode (OldMI, 0) <> 0 then
  248. DefaultVideoModeSelector := false
  249. else
  250. begin
  251. with MI do
  252. begin
  253. cb := 8;
  254. fbType := 1;
  255. if VideoMode.Color then
  256. Color := Colors_16
  257. else
  258. Color := Colors_2;
  259. Col := VideoMode.Col;
  260. Row := VideoMode.Row;
  261. end;
  262. if VioSetMode (MI, 0) = 0 then
  263. if VioGetBuf (VideoBuf, PWord (@VideoBufSize)^, 0) = 0 then
  264. begin
  265. VideoBuf := SelToFlat (TFarPtr (VideoBuf));
  266. DefaultVideoModeSelector := true;
  267. SetHighBitBlink (true);
  268. CheckCellHeight;
  269. SetCursorType (LastCursorType);
  270. ClearScreen;
  271. end
  272. else
  273. begin
  274. DefaultVideoModeSelector := false;
  275. VioSetMode (OldMI, 0);
  276. VioGetBuf (VideoBuf, PWord (@VideoBufSize)^, 0);
  277. VideoBuf := SelToFlat (TFarPtr (VideoBuf));
  278. SetHighBitBlink (true);
  279. CheckCellHeight;
  280. SetCursorType (LastCursorType);
  281. ClearScreen;
  282. end
  283. else
  284. begin
  285. DefaultVideoModeSelector := false;
  286. VioGetBuf (VideoBuf, PWord (@VideoBufSize)^, 0);
  287. VideoBuf := SelToFlat (TFarPtr (VideoBuf));
  288. SetHighBitBlink (true);
  289. SetCursorType (LastCursorType);
  290. end;
  291. end;
  292. end;
  293. procedure SysClearScreen;
  294. begin
  295. VioScrollDn (0, 0, word (-1), word (-1), word (-1), PWord (@EmptyCell)^, 0);
  296. Move (VideoBuf^, OldVideoBuf^, VideoBufSize);
  297. end;
  298. {$ASMMODE INTEL}
  299. procedure SysUpdateScreen (Force: boolean);
  300. var SOfs, CLen: cardinal;
  301. begin
  302. if LockUpdateScreen = 0 then
  303. begin
  304. if not (Force) then
  305. asm
  306. cld
  307. mov esi, VideoBuf
  308. mov edi, OldVideoBuf
  309. mov eax, VideoBufSize
  310. mov ecx, eax
  311. shr ecx, 1
  312. shr ecx, 1
  313. repe
  314. cmpsd
  315. je @no_update
  316. inc ecx
  317. mov edx, eax
  318. mov ebx, ecx
  319. shl ebx, 1
  320. shl ebx, 1
  321. sub edx, ebx
  322. mov SOfs, edx
  323. mov Force, 1
  324. std
  325. mov edi, eax
  326. mov esi, VideoBuf
  327. add eax, esi
  328. sub eax, 4
  329. mov esi, eax
  330. mov eax, OldVideoBuf
  331. add eax, edi
  332. sub eax, 4
  333. mov edi, eax
  334. repe
  335. cmpsd
  336. inc ecx
  337. shl ecx, 1
  338. shl ecx, 1
  339. mov CLen, ecx
  340. @no_update:
  341. end
  342. else
  343. begin
  344. SOfs := 0;
  345. CLen := VideoBufSize;
  346. end;
  347. if Force then
  348. begin
  349. VioShowBuf (SOfs, CLen, 0);
  350. Move (VideoBuf^ [SOfs div SizeOf (TVideoCell)],
  351. OldVideoBuf^ [SOfs div SizeOf (TVideoCell)], CLen);
  352. end;
  353. end;
  354. end;
  355. Const
  356. SysVideoDriver : TVideoDriver = (
  357. InitDriver : @SysInitVideo;
  358. DoneDriver : @SysDoneVideo;
  359. UpdateScreen : @SysUpdateScreen;
  360. ClearScreen : @SysClearScreen;
  361. SetVideoMode : Nil;
  362. HasVideoMode : Nil;
  363. SetCursorPos : @SysSetCursorPos;
  364. GetCursorType : @SysGetCursorType;
  365. SetCursorType : @SysSetCursorType;
  366. GetCapabilities : @SysGetCapabilities
  367. );
  368. initialization
  369. SetVideoDriver(SysVideoDriver);
  370. RegisterVideoModes;
  371. TargetEntry;
  372. finalization
  373. UnRegisterVideoModes;
  374. end.
  375. {
  376. $Log$
  377. Revision 1.5 2001-09-21 19:50:19 michael
  378. + Merged driver support from fixbranch
  379. Revision 1.4 2001/02/04 01:55:05 hajny
  380. * one more correction (not crucial)
  381. Revision 1.2.2.3 2001/09/21 18:42:08 michael
  382. + Implemented support for custom video drivers.
  383. Revision 1.2.2.2 2001/02/04 02:02:28 hajny
  384. * corrections from the main branch merged
  385. Revision 1.3 2001/02/01 21:35:36 hajny
  386. * correction of a previously introduced bug
  387. Revision 1.2 2001/01/23 20:23:56 hajny
  388. * another little optimization of UpdateScreen
  389. Revision 1.1 2001/01/13 11:03:58 peter
  390. * API 2 RTL commit
  391. }