video.pp 11 KB

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