video.pp 11 KB

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