video.pp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  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. 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. begin
  293. if not (Force) then
  294. asm
  295. push ebx
  296. push esi
  297. push edi
  298. cld
  299. mov esi, VideoBuf
  300. mov edi, OldVideoBuf
  301. mov eax, VideoBufSize
  302. mov ecx, eax
  303. shr ecx, 1
  304. shr ecx, 1
  305. repe
  306. cmpsd
  307. je @no_update
  308. inc ecx
  309. mov edx, eax
  310. mov ebx, ecx
  311. shl ebx, 1
  312. shl ebx, 1
  313. sub edx, ebx
  314. mov SOfs, edx
  315. mov Force, 1
  316. std
  317. mov edi, eax
  318. mov esi, VideoBuf
  319. add eax, esi
  320. sub eax, 4
  321. mov esi, eax
  322. mov eax, OldVideoBuf
  323. add eax, edi
  324. sub eax, 4
  325. mov edi, eax
  326. repe
  327. cmpsd
  328. inc ecx
  329. shl ecx, 1
  330. shl ecx, 1
  331. mov CLen, ecx
  332. @no_update:
  333. pop edi
  334. pop esi
  335. pop ebx
  336. end ['eax', 'ecx', 'edx']
  337. else
  338. begin
  339. SOfs := 0;
  340. CLen := VideoBufSize;
  341. end;
  342. // .MVC. Move video buffer to system video buffer.
  343. Move(VideoBuf^,SysVideoBuf^,VideoBufSize);
  344. if Force then
  345. begin
  346. VioShowBuf (SOfs, CLen, 0);
  347. Move (VideoBuf^ [SOfs div SizeOf (TVideoCell)],
  348. OldVideoBuf^ [SOfs div SizeOf (TVideoCell)], CLen);
  349. end;
  350. end;
  351. Const
  352. SysVideoDriver : TVideoDriver = (
  353. InitDriver : @SysInitVideo;
  354. DoneDriver : @SysDoneVideo;
  355. UpdateScreen : @SysUpdateScreen;
  356. ClearScreen : @SysClearScreen;
  357. SetVideoMode : @SysSetVideoMode;
  358. GetVideoModeCount : @SysGetVideoModeCount;
  359. GetVideoModeData : @SysGetVideoModedata;
  360. SetCursorPos : @SysSetCursorPos;
  361. GetCursorType : @SysGetCursorType;
  362. SetCursorType : @SysSetCursorType;
  363. GetCapabilities : @SysGetCapabilities
  364. );
  365. procedure TargetEntry;
  366. var
  367. PScr: pointer;
  368. begin
  369. {Remember original video mode, cursor type and high bit behaviour setting}
  370. OrigVioMode.cb := SizeOf (OrigVioMode);
  371. VioGetMode (OrigVioMode, 0);
  372. VioGetCurType (OrigCurType, 0);
  373. VioGetCurPos (OrigCurRow, OrigCurCol, 0);
  374. with OrigHighBit do
  375. begin
  376. cb := 6;
  377. rType := 2;
  378. end;
  379. VioGetState (OrigHighBit, 0);
  380. { Register the curent video mode in reserved slot in System Modes}
  381. with OrigVioMode do
  382. begin
  383. {Assume we have at least 16 colours available in "colour" modes}
  384. SysVMD[SysVideoModeCount-1].Col:=Col;
  385. SysVMD[SysVideoModeCount-1].Row:=Row;
  386. SysVMD[SysVideoModeCount-1].Color:=(Color >= Colors_16);
  387. end;
  388. {Get the address of the original videobuffer and size.}
  389. if VioGetBuf (PScr, PWord (@OrigScreenSize)^, 0) = 0 then
  390. begin
  391. PScr := SelToFlat (cardinal (PScr));
  392. GetMem (OrigScreen, OrigScreenSize);
  393. Move (PScr^, OrigScreen^, OrigScreenSize);
  394. end;
  395. end;
  396. initialization
  397. SetVideoDriver(SysVideoDriver);
  398. TargetEntry;
  399. end.