video.pp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  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;
  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. LowAscii := true;
  72. SetCursorType (LastCursorType);
  73. { Get the address of the videobuffer.}
  74. if VioGetBuf (SysVideoBuf, PWord (@VideoBufSize)^, 0) = 0 then
  75. begin
  76. SysVideoBuf := SelToFlat (cardinal (SysVideoBuf));
  77. SetHighBitBlink (true);
  78. end
  79. else
  80. ErrorHandler (errVioInit, nil);
  81. end;
  82. procedure SysSetCursorPos (NewCursorX, NewCursorY: word);
  83. begin
  84. if VioSetCurPos (NewCursorY, NewCursorX, 0) = 0 then
  85. begin
  86. CursorX := NewCursorX;
  87. CursorY := NewCursorY;
  88. end
  89. else
  90. {Do not set an error code; people should fix invalid NewCursorX
  91. or NewCursorY values when designing, there is no need for detecting
  92. these errors at runtime.}
  93. RunError (225);
  94. end;
  95. function SysGetCursorType: word;
  96. var CD: TVioCursorInfo;
  97. begin
  98. VioGetCurType (CD, 0); {Never fails, because handle is default handle.}
  99. with CD do
  100. begin
  101. CursorLines := Succ (cEnd) - yStart;
  102. if Attr = word (-1) then
  103. SysGetCursorType := crHidden
  104. else
  105. {Because the cursor's start and end lines are returned, we'll have
  106. to guess heuristically what cursor type we have.}
  107. if CursorLines = 0 then
  108. {Probably this does not occur, but you'll never know.}
  109. SysGetCursorType := crHidden
  110. else if CursorLines <= Succ (CellHeight div 4) then
  111. SysGetCursorType := crUnderline
  112. else if CursorLines <= Succ (CellHeight div 2) then
  113. SysGetCursorType := crHalfBlock
  114. else
  115. SysGetCursorType := crBlock;
  116. end;
  117. end;
  118. procedure SysSetCursorType (NewType: word);
  119. var CD: TVioCursorInfo;
  120. begin
  121. VioGetCurType (CD, 0);
  122. with CD do
  123. begin
  124. case NewType of
  125. crHidden: Attr := word (-1);
  126. crUnderline:
  127. begin
  128. Attr := 0;
  129. yStart := word (-90);
  130. cEnd := word (-100);
  131. end;
  132. crHalfBlock:
  133. begin
  134. Attr := 0;
  135. yStart := word (-50);
  136. cEnd := word (-100);
  137. end;
  138. crBlock:
  139. begin
  140. Attr := 0;
  141. yStart := 0;
  142. cEnd := word (-100);
  143. end;
  144. end;
  145. VioSetCurType (CD, 0);
  146. VioGetCurType (CD, 0);
  147. CursorLines := Succ (cEnd) - yStart;
  148. end;
  149. end;
  150. procedure SysClearScreen;
  151. begin
  152. VioScrollDn (0, 0, word (-1), word (-1), word (-1), PWord (@EmptyCell)^, 0);
  153. FillWord (SysVideoBuf^, VideoBufSize shr 1, PWord (@EmptyCell)^);
  154. end;
  155. procedure SysDoneVideo;
  156. var PScr: pointer;
  157. ScrSize: cardinal;
  158. begin
  159. LastCursorType := GetCursorType;
  160. SysClearScreen;
  161. {Restore original settings}
  162. VioSetMode (OrigVioMode, 0);
  163. CheckCellHeight;
  164. {Set CursorX and CursorY}
  165. SetCursorPos (0, 0);
  166. VioSetState (OrigHighBit, 0);
  167. VioSetCurType (OrigCurType, 0);
  168. VioSetCurPos (OrigCurRow, OrigCurCol, 0);
  169. if (OrigScreenSize <> 0) and (OrigScreen <> nil) then
  170. begin
  171. ScrSize := 0;
  172. if (VioGetBuf (PScr, PWord (@ScrSize)^, 0) = 0) and
  173. (ScrSize = OrigScreenSize) then
  174. begin
  175. PScr := SelToFlat (cardinal (PScr));
  176. Move (OrigScreen^, PScr^, OrigScreenSize);
  177. VioShowBuf (0, ScrSize, 0);
  178. end;
  179. end;
  180. end;
  181. function SysGetCapabilities: word;
  182. begin
  183. SysGetCapabilities := $3F;
  184. end;
  185. function SysVideoModeSelector (const VideoMode: TVideoMode): boolean;
  186. var OldMI, MI: TVioModeInfo;
  187. begin
  188. OldMI.cb := SizeOf (OldMI);
  189. if VioGetMode (OldMI, 0) <> 0 then
  190. SysVideoModeSelector := false
  191. else
  192. begin
  193. with MI do
  194. begin
  195. cb := 8;
  196. fbType := 1;
  197. if VideoMode.Color then
  198. Color := Colors_16
  199. else
  200. Color := Colors_2;
  201. Col := VideoMode.Col;
  202. Row := VideoMode.Row;
  203. end;
  204. if VioSetMode (MI, 0) = 0 then
  205. if VioGetBuf (SysVideoBuf, PWord (@VideoBufSize)^, 0) = 0 then
  206. begin
  207. SysVideoBuf := SelToFlat (cardinal (SysVideoBuf));
  208. SysVideoModeSelector := true;
  209. SetHighBitBlink (true);
  210. CheckCellHeight;
  211. SetCursorType (LastCursorType);
  212. SysClearScreen;
  213. end
  214. else
  215. begin
  216. SysVideoModeSelector := false;
  217. VioSetMode (OldMI, 0);
  218. VioGetBuf (SysVideoBuf, PWord (@VideoBufSize)^, 0);
  219. SysVideoBuf := SelToFlat (cardinal (SysVideoBuf));
  220. SetHighBitBlink (true);
  221. CheckCellHeight;
  222. SetCursorType (LastCursorType);
  223. SysClearScreen;
  224. end
  225. else
  226. begin
  227. SysVideoModeSelector := false;
  228. VioGetBuf (SysVideoBuf, PWord (@VideoBufSize)^, 0);
  229. SysVideoBuf := SelToFlat (cardinal (SysVideoBuf));
  230. SetHighBitBlink (true);
  231. SetCursorType (LastCursorType);
  232. end;
  233. end;
  234. end;
  235. Const
  236. SysVideoModeCount = 6;
  237. SysVMD : Array[0..SysVideoModeCount-1] of TVideoMode = (
  238. (Col: 40; Row: 25; Color: True),
  239. (Col: 80; Row: 25; Color: True),
  240. (Col: 80; Row: 30; Color: True),
  241. (Col: 80; Row: 43; Color: True),
  242. (Col: 80; Row: 50; Color: True),
  243. (Col: 80; Row: 25; Color: True) // Reserved for TargetEntry
  244. );
  245. { .MVC. were commented:
  246. BW modes are rejected on my (colour) configuration. I can't imagine
  247. OS/2 running on MCGA anyway... ;-)
  248. (Col: 40; Row: 25;Color: False),
  249. (Col: 80; Row: 25;Color: False),
  250. The following modes wouldn't work on plain VGA; is it useful to check
  251. for their availability on the program startup?
  252. (Col: 132;Row: 25;Color: True),
  253. (Col: 132;Row: 30;Color: True),
  254. (Col: 132;Row: 43;Color: True),
  255. (Col: 132;Row: 50;Color: True),
  256. }
  257. Function SysSetVideoMode (Const Mode : TVideoMode) : Boolean;
  258. Var
  259. I : Integer;
  260. begin
  261. I:=SysVideoModeCount-1;
  262. SysSetVideoMode:=False;
  263. While (I>=0) and Not SysSetVideoMode do
  264. If (Mode.col=SysVMD[i].col) and
  265. (Mode.Row=SysVMD[i].Row) and
  266. (Mode.Color=SysVMD[i].Color) then
  267. SysSetVideoMode:=True
  268. else
  269. Dec(I);
  270. If SysSetVideoMode then
  271. begin
  272. if SysVideoModeSelector(Mode) then
  273. begin;
  274. ScreenWidth:=SysVMD[I].Col;
  275. ScreenHeight:=SysVMD[I].Row;
  276. ScreenColor:=SysVMD[I].Color;
  277. end else SysSetVideoMode := false;
  278. end;
  279. end;
  280. Function SysGetVideoModeData (Index : Word; Var Data : TVideoMode) : boolean;
  281. begin
  282. SysGetVideoModeData:=(Index<=SysVideoModeCount);
  283. If SysGetVideoModeData then
  284. Data:=SysVMD[Index];
  285. end;
  286. Function SysGetVideoModeCount : Word;
  287. begin
  288. SysGetVideoModeCount:=SysVideoModeCount;
  289. end;
  290. {$ASMMODE INTEL}
  291. procedure SysUpdateScreen (Force: boolean);
  292. var SOfs, CLen: cardinal;
  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. VioShowBuf (SOfs, CLen, 0);
  348. Move (VideoBuf^ [SOfs div SizeOf (TVideoCell)],
  349. OldVideoBuf^ [SOfs div SizeOf (TVideoCell)], CLen);
  350. end;
  351. end;
  352. Const
  353. SysVideoDriver : TVideoDriver = (
  354. InitDriver : @SysInitVideo;
  355. DoneDriver : @SysDoneVideo;
  356. UpdateScreen : @SysUpdateScreen;
  357. ClearScreen : @SysClearScreen;
  358. SetVideoMode : @SysSetVideoMode;
  359. GetVideoModeCount : @SysGetVideoModeCount;
  360. GetVideoModeData : @SysGetVideoModedata;
  361. SetCursorPos : @SysSetCursorPos;
  362. GetCursorType : @SysGetCursorType;
  363. SetCursorType : @SysSetCursorType;
  364. GetCapabilities : @SysGetCapabilities
  365. );
  366. procedure TargetEntry;
  367. var
  368. PScr: pointer;
  369. begin
  370. {Remember original video mode, cursor type and high bit behaviour setting}
  371. OrigVioMode.cb := SizeOf (OrigVioMode);
  372. VioGetMode (OrigVioMode, 0);
  373. VioGetCurType (OrigCurType, 0);
  374. VioGetCurPos (OrigCurRow, OrigCurCol, 0);
  375. with OrigHighBit do
  376. begin
  377. cb := 6;
  378. rType := 2;
  379. end;
  380. VioGetState (OrigHighBit, 0);
  381. { Register the curent video mode in reserved slot in System Modes}
  382. with OrigVioMode do
  383. begin
  384. {Assume we have at least 16 colours available in "colour" modes}
  385. SysVMD[SysVideoModeCount-1].Col:=Col;
  386. SysVMD[SysVideoModeCount-1].Row:=Row;
  387. SysVMD[SysVideoModeCount-1].Color:=(Color >= Colors_16);
  388. end;
  389. {Get the address of the original videobuffer and size.}
  390. if VioGetBuf (PScr, PWord (@OrigScreenSize)^, 0) = 0 then
  391. begin
  392. PScr := SelToFlat (cardinal (PScr));
  393. GetMem (OrigScreen, OrigScreenSize);
  394. Move (PScr^, OrigScreen^, OrigScreenSize);
  395. end;
  396. end;
  397. initialization
  398. SetVideoDriver(SysVideoDriver);
  399. TargetEntry;
  400. end.