video.pp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  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 (cardinal (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 (cardinal (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 (cardinal (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 (cardinal (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 (cardinal (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. if SysVideoModeSelector(Mode) then
  269. begin;
  270. ScreenWidth:=SysVMD[I].Col;
  271. ScreenHeight:=SysVMD[I].Row;
  272. ScreenColor:=SysVMD[I].Color;
  273. end else SysSetVideoMode := false;
  274. end;
  275. end;
  276. Function SysGetVideoModeData (Index : Word; Var Data : TVideoMode) : boolean;
  277. begin
  278. SysGetVideoModeData:=(Index<=SysVideoModeCount);
  279. If SysGetVideoModeData then
  280. Data:=SysVMD[Index];
  281. end;
  282. Function SysGetVideoModeCount : Word;
  283. begin
  284. SysGetVideoModeCount:=SysVideoModeCount;
  285. end;
  286. procedure SysClearScreen;
  287. begin
  288. VioScrollDn (0, 0, word (-1), word (-1), word (-1), PWord (@EmptyCell)^, 0);
  289. Move (VideoBuf^, OldVideoBuf^, VideoBufSize);
  290. end;
  291. {$ASMMODE INTEL}
  292. procedure SysUpdateScreen (Force: boolean);
  293. var SOfs, CLen: cardinal;
  294. begin
  295. if not (Force) then
  296. asm
  297. push ebx
  298. push esi
  299. push edi
  300. cld
  301. mov esi, VideoBuf
  302. mov edi, OldVideoBuf
  303. mov eax, VideoBufSize
  304. mov ecx, eax
  305. shr ecx, 1
  306. shr ecx, 1
  307. repe
  308. cmpsd
  309. je @no_update
  310. inc ecx
  311. mov edx, eax
  312. mov ebx, ecx
  313. shl ebx, 1
  314. shl ebx, 1
  315. sub edx, ebx
  316. mov SOfs, edx
  317. mov Force, 1
  318. std
  319. mov edi, eax
  320. mov esi, VideoBuf
  321. add eax, esi
  322. sub eax, 4
  323. mov esi, eax
  324. mov eax, OldVideoBuf
  325. add eax, edi
  326. sub eax, 4
  327. mov edi, eax
  328. repe
  329. cmpsd
  330. inc ecx
  331. shl ecx, 1
  332. shl ecx, 1
  333. mov CLen, ecx
  334. @no_update:
  335. pop edi
  336. pop esi
  337. pop ebx
  338. end ['eax', 'ecx', 'edx']
  339. else
  340. begin
  341. SOfs := 0;
  342. CLen := VideoBufSize;
  343. end;
  344. // .MVC. Move video buffer to system video buffer.
  345. Move(VideoBuf^,SysVideoBuf^,VideoBufSize);
  346. if Force then
  347. begin
  348. VioShowBuf (SOfs, CLen, 0);
  349. Move (VideoBuf^ [SOfs div SizeOf (TVideoCell)],
  350. OldVideoBuf^ [SOfs div SizeOf (TVideoCell)], CLen);
  351. end;
  352. end;
  353. Const
  354. SysVideoDriver : TVideoDriver = (
  355. InitDriver : @SysInitVideo;
  356. DoneDriver : @SysDoneVideo;
  357. UpdateScreen : @SysUpdateScreen;
  358. ClearScreen : @SysClearScreen;
  359. SetVideoMode : @SysSetVideoMode;
  360. GetVideoModeCount : @SysGetVideoModeCount;
  361. GetVideoModeData : @SysGetVideoModedata;
  362. SetCursorPos : @SysSetCursorPos;
  363. GetCursorType : @SysGetCursorType;
  364. SetCursorType : @SysSetCursorType;
  365. GetCapabilities : @SysGetCapabilities
  366. );
  367. procedure TargetEntry;
  368. var
  369. PScr: pointer;
  370. begin
  371. {Remember original video mode, cursor type and high bit behaviour setting}
  372. OrigVioMode.cb := SizeOf (OrigVioMode);
  373. VioGetMode (OrigVioMode, 0);
  374. VioGetCurType (OrigCurType, 0);
  375. VioGetCurPos (OrigCurRow, OrigCurCol, 0);
  376. with OrigHighBit do
  377. begin
  378. cb := 6;
  379. rType := 2;
  380. end;
  381. VioGetState (OrigHighBit, 0);
  382. { Register the curent video mode in reserved slot in System Modes}
  383. with OrigVioMode do
  384. begin
  385. {Assume we have at least 16 colours available in "colour" modes}
  386. SysVMD[SysVideoModeCount-1].Col:=Col;
  387. SysVMD[SysVideoModeCount-1].Row:=Row;
  388. SysVMD[SysVideoModeCount-1].Color:=(Color >= Colors_16);
  389. end;
  390. {Get the address of the original videobuffer and size.}
  391. if VioGetBuf (PScr, PWord (@OrigScreenSize)^, 0) = 0 then
  392. begin
  393. PScr := SelToFlat (cardinal (PScr));
  394. GetMem (OrigScreen, OrigScreenSize);
  395. Move (PScr^, OrigScreen^, OrigScreenSize);
  396. end;
  397. end;
  398. initialization
  399. SetVideoDriver(SysVideoDriver);
  400. TargetEntry;
  401. end.
  402. {
  403. $Log$
  404. Revision 1.11 2004-09-13 20:58:58 hajny
  405. * SysSetVideoMode corrected to reflect SysVideoModeSelector result
  406. Revision 1.10 2004/05/24 19:33:22 hajny
  407. * regcall update
  408. Revision 1.9 2003/10/07 21:26:35 hajny
  409. * stdcall fixes and asm routines cleanup
  410. Revision 1.8 2003/10/03 21:46:41 peter
  411. * stdcall fixes
  412. Revision 1.7 2002/09/07 16:01:25 peter
  413. * old logs removed and tabs fixed
  414. }