mouse.pp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  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. Mouse unit for Go32v2
  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 Mouse;
  14. interface
  15. {$i mouseh.inc}
  16. { tells the mouse unit to draw the mouse cursor itself }
  17. procedure DoCustomMouse(b : boolean);
  18. implementation
  19. uses
  20. video,go32;
  21. {$i mouse.inc}
  22. var
  23. RealSeg : Word; { Real mode segment }
  24. RealOfs : Word; { Real mode offset }
  25. CurrentMask : word;
  26. MouseCallback : Pointer; { Mouse call back ptr }
  27. UnderNT: boolean;
  28. {$ifdef DEBUG}
  29. EntryEDI,EntryESI : longint;
  30. EntryDS,EntryES : word;
  31. {$endif DEBUG}
  32. { Real mode registers in text segment below $ffff limit
  33. for Windows NT
  34. NOTE this might cause problem if someone want to
  35. protect text section against writing (would be possible
  36. with CWSDPMI under raw dos, not implemented yet !) }
  37. ActionRegs : TRealRegs;external name '___v2prt0_rmcb_regs';
  38. v2prt0_ds_alias : word;external name '___v2prt0_ds_alias';
  39. const
  40. MousePresent : boolean = false;
  41. {$ifdef DEBUG}
  42. MouseError : longint = 0;
  43. CallCounter : longint = 0;
  44. {$endif DEBUG}
  45. drawmousecursor : boolean = false;
  46. mouseisvisible : boolean = false;
  47. { position where the mouse was drawn the last time }
  48. oldmousex : longint = -1;
  49. oldmousey : longint = -1;
  50. mouselock : boolean = false;
  51. { if the cursor is drawn by this the unit, we must be careful }
  52. { when drawing while the interrupt handler is called }
  53. procedure lockmouse;assembler;
  54. asm
  55. .Ltrylockagain:
  56. movb $1,%al
  57. xchgb mouselock,%al
  58. orb %al,%al
  59. jne .Ltrylockagain
  60. end;
  61. procedure unlockmouse;
  62. begin
  63. mouselock:=false;
  64. end;
  65. {$ASMMODE ATT}
  66. procedure MouseInt;assembler;
  67. asm
  68. movb %bl,mousebuttons
  69. movw %cx,mousewherex
  70. movw %dx,mousewherey
  71. shrw $3,%cx
  72. shrw $3,%dx
  73. { should we draw the mouse cursor? }
  74. cmpb $0,drawmousecursor
  75. je .Lmouse_nocursor
  76. cmpb $0,mouseisvisible
  77. je .Lmouse_nocursor
  78. pushw %fs
  79. pushl %eax
  80. pushl %edi
  81. { check lock }
  82. movb $1,%al
  83. xchgb mouselock,%al
  84. orb %al,%al
  85. { don't update the cursor yet, because hide/showcursor is called }
  86. jne .Ldont_draw
  87. { load start of video buffer }
  88. movzwl videoseg,%edi
  89. shll $4,%edi
  90. movw dosmemselector,%fs
  91. { calculate address of old mouse cursor }
  92. movl oldmousey,%eax
  93. imulw screenwidth,%ax
  94. addl oldmousex,%eax
  95. leal 1(%edi,%eax,2),%eax
  96. { remove old cursor }
  97. xorb $0x7f,%fs:(%eax)
  98. { store position of old cursor }
  99. movzwl %cx,%ecx
  100. movl %ecx,oldmousex
  101. movzwl %dx,%edx
  102. movl %edx,oldmousey
  103. { calculate address of new cursor }
  104. movl %edx,%eax
  105. imulw screenwidth,%ax
  106. addl %ecx,%eax
  107. leal 1(%edi,%eax,2),%eax
  108. { draw new cursor }
  109. xorb $0x7f,%fs:(%eax)
  110. { unlock mouse }
  111. movb $0,mouselock
  112. .Ldont_draw:
  113. popl %edi
  114. popl %eax
  115. popw %fs
  116. .Lmouse_nocursor:
  117. cmpb MouseEventBufSize,PendingMouseEvents
  118. je .Lmouse_exit
  119. movl PendingMouseTail,%edi
  120. movw %bx,(%edi)
  121. movw %cx,2(%edi)
  122. movw %dx,4(%edi)
  123. movw $0,6(%edi)
  124. addl $8,%edi
  125. leal PendingMouseEvent,%eax
  126. addl MouseEventBufSize*8,%eax
  127. cmpl %eax,%edi
  128. jne .Lmouse_nowrap
  129. leal PendingMouseEvent,%edi
  130. .Lmouse_nowrap:
  131. movl %edi,PendingMouseTail
  132. incb PendingMouseEvents
  133. .Lmouse_exit:
  134. end;
  135. PROCEDURE Mouse_Trap; ASSEMBLER;
  136. ASM
  137. PUSH %ES; { Save ES register }
  138. PUSH %DS; { Save DS register }
  139. PUSHL %EDI; { Save register }
  140. PUSHL %ESI; { Save register }
  141. { ; caution : ds is not the selector for our data !! }
  142. {$ifdef DEBUG}
  143. MOVL %EDI,%ES:EntryEDI
  144. MOVL %ESI,%ES:EntryESI
  145. MOVW %DS,%AX
  146. MOVW %AX,%ES:EntryDS
  147. MOVW %ES,%AX
  148. MOVW %AX,%ES:EntryES
  149. {$endif DEBUG}
  150. { movw %cs:v2prt0_ds_alias,%ax v2prt0 is not locked !!
  151. movw %ax,%ds
  152. movw %ax,%es }
  153. PUSH %ES; { Push data seg }
  154. POP %DS; { Load data seg }
  155. {$ifdef DEBUG}
  156. incl callcounter
  157. CMPL $ACTIONREGS,%edi
  158. JE .L_ActionRegsOK
  159. INCL MouseError
  160. JMP .L_NoCallBack
  161. .L_ActionRegsOK:
  162. {$endif DEBUG}
  163. MOVL MOUSECALLBACK, %EAX; { Fetch callback addr }
  164. CMPL $0, %EAX; { Check for nil ptr }
  165. JZ .L_NoCallBack; { Ignore if nil }
  166. MOVL %EDI,%EAX; { %EAX = @actionregs }
  167. MOVL (%EAX), %EDI; { EDI from actionregs }
  168. MOVL 4(%EAX), %ESI; { ESI from actionregs }
  169. MOVL 16(%EAX), %EBX; { EBX from actionregs }
  170. MOVL 20(%EAX), %EDX; { EDX from actionregs }
  171. MOVL 24(%EAX), %ECX; { ECX from actionregs }
  172. MOVL 28(%EAX), %EAX; { EAX from actionregs }
  173. CALL *MOUSECALLBACK; { Call callback proc }
  174. .L_NoCallBack:
  175. POPL %ESI; { Recover register }
  176. POPL %EDI; { Recover register }
  177. POP %DS; { Restore DS register }
  178. POP %ES; { Restore ES register }
  179. { This works for WinNT
  180. movzwl %si,%eax
  181. but CWSDPMI need this }
  182. movl %esi,%eax
  183. MOVL %ds:(%Eax), %EAX;
  184. MOVL %EAX, %ES:42(%EDI); { Set as return addr }
  185. ADDW $4, %ES:46(%EDI); { adjust stack }
  186. IRET; { Interrupt return }
  187. END;
  188. PROCEDURE Mouse_Trap_NT; ASSEMBLER;
  189. ASM
  190. pushl %eax;
  191. PUSH %ES; { Save ES register }
  192. PUSH %DS; { Save DS register }
  193. PUSH %FS; { Save FS register }
  194. PUSHL %EDI; { Save register }
  195. PUSHL %ESI; { Save register }
  196. pushl %ebx;
  197. pushl %ecx;
  198. pushl %edx;
  199. { ; caution : ds is not the selector for our data !! }
  200. {$ifdef DEBUG}
  201. MOVL %EDI,%ES:EntryEDI
  202. MOVL %ESI,%ES:EntryESI
  203. MOVW %DS,%AX
  204. MOVW %AX,%ES:EntryDS
  205. MOVW %ES,%AX
  206. MOVW %AX,%ES:EntryES
  207. {$endif DEBUG}
  208. { movw %cs:v2prt0_ds_alias,%ax v2prt0 is not locked !!
  209. movw %ax,%ds
  210. movw %ax,%es }
  211. PUSH %ES; { Push data seg }
  212. POP %DS; { Load data seg }
  213. {$ifdef DEBUG}
  214. incl callcounter
  215. CMPL $ACTIONREGS,%edi
  216. JE .L_ActionRegsOK
  217. INCL MouseError
  218. JMP .L_NoCallBack
  219. .L_ActionRegsOK:
  220. {$endif DEBUG}
  221. MOVL MOUSECALLBACK, %EAX; { Fetch callback addr }
  222. CMPL $0, %EAX; { Check for nil ptr }
  223. JZ .L_NoCallBack; { Ignore if nil }
  224. MOVL %EDI,%EAX; { %EAX = @actionregs }
  225. MOVL (%EAX), %EDI; { EDI from actionregs }
  226. MOVL 4(%EAX), %ESI; { ESI from actionregs }
  227. MOVL 16(%EAX), %EBX; { EBX from actionregs }
  228. MOVL 20(%EAX), %EDX; { EDX from actionregs }
  229. MOVL 24(%EAX), %ECX; { ECX from actionregs }
  230. MOVL 28(%EAX), %EAX; { EAX from actionregs }
  231. CALL *MOUSECALLBACK; { Call callback proc }
  232. .L_NoCallBack:
  233. popl %edx;
  234. popl %ecx;
  235. popl %ebx;
  236. POPL %ESI; { Recover register }
  237. POPL %EDI; { Recover register }
  238. POP %FS; { Restore FS register }
  239. POP %DS; { Restore DS register }
  240. POP %ES; { Restore ES register }
  241. movw %ds,%ax;
  242. lsl %eax,%eax;
  243. cmpl %eax,%esi;
  244. ja .Lsimplecopy;
  245. movzwl %si,%eax;
  246. jmp .Lcopyend;
  247. .Lsimplecopy:
  248. movl %esi,%eax;
  249. .Lcopyend:
  250. MOVL %ds:(%Eax), %EAX;
  251. MOVL %EAX, %ES:42(%EDI); { Set as return addr }
  252. ADDW $4, %ES:46(%EDI); { adjust stack }
  253. popl %eax;
  254. IRET; { Interrupt return }
  255. END;
  256. Function Allocate_mouse_bridge : boolean;
  257. var
  258. error : word;
  259. begin
  260. ASM
  261. LEAL ACTIONREGS, %EDI; { Addr of actionregs }
  262. LEAL MOUSE_TRAP, %ESI; { Procedure address }
  263. CMPB $0, UnderNT
  264. JZ .LGo32
  265. LEAL MOUSE_TRAP_NT, %ESI; { Procedure address }
  266. .LGo32:
  267. PUSH %DS; { Save DS segment }
  268. PUSH %ES; { Save ES segment }
  269. MOVW v2prt0_ds_alias,%ES; { ES now has dataseg alias that is never invalid }
  270. PUSH %CS;
  271. POP %DS; { DS now has codeseg }
  272. MOVW $0x303, %AX; { Function id }
  273. INT $0x31; { Call DPMI bridge }
  274. JNC .L_call_ok; { Branch if ok }
  275. POP %ES; { Restore ES segment }
  276. POP %DS; { Restore DS segment }
  277. MOVW $0,REALSEG;
  278. MOVW $0,REALOFS;
  279. JMP .L_exit
  280. .L_call_ok:
  281. POP %ES; { Restore ES segment }
  282. POP %DS; { Restore DS segment }
  283. MOVW %CX,REALSEG; { Transfer real seg }
  284. MOVW %DX,REALOFS; { Transfer real ofs }
  285. MOVW $0, %AX; { Force error to zero }
  286. .L_exit:
  287. MOVW %AX, ERROR; { Return error state }
  288. END;
  289. Allocate_mouse_bridge:=error=0;
  290. end;
  291. Procedure Release_mouse_bridge;
  292. begin
  293. ASM
  294. MOVW $0x304, %AX; { Set function id }
  295. MOVW REALSEG, %CX; { Bridged real seg }
  296. MOVW REALOFS, %DX; { Bridged real ofs }
  297. INT $0x31; { Release bridge }
  298. MOVW $0,REALSEG;
  299. MOVW $0,REALOFS;
  300. END;
  301. end;
  302. PROCEDURE Mouse_Action (Mask : Word; P : Pointer);
  303. VAR
  304. Error : Word;
  305. Rg : TRealRegs;
  306. BEGIN
  307. Error := 0; { Preset no error }
  308. If (P <> MouseCallBack) or (Mask<>CurrentMask) Then { Check func different }
  309. Begin
  310. { Remove old calback }
  311. If (CurrentMask <> 0) Then
  312. Begin
  313. Rg.AX := 12; { Function id }
  314. Rg.CX := 0; { Zero mask register }
  315. Rg.ES := 0; { Zero proc seg }
  316. Rg.DX := 0; { Zero proc ofs }
  317. RealIntr($33, Rg); { Stop INT 33 callback }
  318. End;
  319. if RealSeg=0 then
  320. error:=1;
  321. { test addresses for Windows NT }
  322. if (longint(@actionregs)>$ffff) {or
  323. (longint(@mouse_trap)>$ffff)} then
  324. begin
  325. error:=1;
  326. end
  327. else If (P = Nil) Then
  328. Begin
  329. Mask := 0; { Zero mask register }
  330. End;
  331. If (Error = 0) Then
  332. Begin
  333. MouseCallback := P; { Set call back addr }
  334. if Mask<>0 then
  335. begin
  336. Rg.AX := 12; { Set function id }
  337. Rg.CX := Mask; { Set mask register }
  338. If Mask<>0 then
  339. begin
  340. Rg.ES := RealSeg; { Real mode segment }
  341. Rg.DX := RealOfs; { Real mode offset }
  342. end
  343. else
  344. begin
  345. Rg.ES:=0;
  346. Rg.DX:=0;
  347. end;
  348. RealIntr($33, Rg); { Set interrupt 33 }
  349. end;
  350. CurrentMask:=Mask;
  351. End;
  352. End;
  353. If (Error <> 0) Then
  354. Begin
  355. Writeln('GO32V2 mouse handler set failed !!');
  356. ReadLn; { Wait for user to see }
  357. End;
  358. END;
  359. { We need to remove the mouse callback before exiting !! PM }
  360. const StoredExit : Pointer = Nil;
  361. FirstMouseInitDone : boolean = false;
  362. procedure MouseSafeExit;
  363. begin
  364. ExitProc:=StoredExit;
  365. if MouseCallBack<>Nil then
  366. Mouse_Action(0, Nil);
  367. if not FirstMouseInitDone then
  368. exit;
  369. FirstMouseInitDone:=false;
  370. Unlock_Code(Pointer(@Mouse_Trap), 400); { Release trap code }
  371. Unlock_Code(Pointer(@Mouse_Trap_NT), 400); { Release trap code }
  372. Unlock_Code(Pointer(@MouseInt), 400); { Lock MouseInt code }
  373. Unlock_Data(ActionRegs, SizeOf(TRealRegs)); { Release registers }
  374. UnLock_Data(MouseCallBack,SizeOf(Pointer));
  375. { unlock Mouse Queue and related stuff ! }
  376. Unlock_Data(PendingMouseEvent,
  377. MouseEventBufSize*Sizeof(TMouseEvent));
  378. Unlock_Data(PendingMouseTail,SizeOf(longint));
  379. Unlock_Data(PendingMouseEvents,sizeof(byte));
  380. Unlock_Data(MouseButtons,SizeOf(byte));
  381. Unlock_Data(MouseWhereX,SizeOf(word));
  382. Unlock_Data(MouseWhereY,SizeOf(word));
  383. Unlock_Data(drawmousecursor,SizeOf(boolean));
  384. Unlock_Data(mouseisvisible,SizeOf(boolean));
  385. Unlock_Data(mouselock,SizeOf(boolean));
  386. Unlock_Data(videoseg,SizeOf(word));
  387. Unlock_Data(dosmemselector,SizeOf(word));
  388. Unlock_Data(screenwidth,SizeOf(word));
  389. Unlock_Data(OldMouseX,SizeOf(longint));
  390. Unlock_Data(OldMouseY,SizeOf(longint));
  391. {$ifdef DEBUG}
  392. Unlock_Data(EntryEDI, SizeOf(longint));
  393. Unlock_Data(EntryESI, SizeOf(longint));
  394. Unlock_Data(EntryDS, SizeOf(word));
  395. Unlock_Data(EntryES, SizeOf(word));
  396. Unlock_Data(MouseError, SizeOf(longint));
  397. Unlock_Data(callcounter, SizeOf(longint));
  398. {$endif DEBUG}
  399. Release_mouse_bridge;
  400. end;
  401. function RunningUnderWINNT: boolean;
  402. var r: trealregs;
  403. begin
  404. fillchar(r,sizeof(r),0);
  405. r.ax:=$3306;
  406. realintr($21,r);
  407. RunningUnderWINNT:=(r.bx=$3205);
  408. end;
  409. procedure SysInitMouse;
  410. begin
  411. UnderNT:=RunningUnderWINNT;
  412. if not MousePresent then
  413. begin
  414. if DetectMouse=0 then
  415. begin
  416. Writeln('No mouse driver found ');
  417. exit;
  418. end
  419. else
  420. MousePresent:=true;
  421. end;
  422. { don't do this twice !! PM }
  423. If not FirstMouseInitDone then
  424. begin
  425. StoredExit:=ExitProc;
  426. ExitProc:=@MouseSafeExit;
  427. Lock_Code(Pointer(@Mouse_Trap), 400); { Lock trap code }
  428. Lock_Code(Pointer(@Mouse_Trap_NT), 400); { Lock trap code }
  429. Lock_Code(Pointer(@MouseInt), 400); { Lock MouseInt code }
  430. Lock_Data(ActionRegs, SizeOf(TRealRegs)); { Lock registers }
  431. Lock_Data(MouseCallBack, SizeOf(pointer));
  432. { lock Mouse Queue and related stuff ! }
  433. Lock_Data(PendingMouseEvent,
  434. MouseEventBufSize*Sizeof(TMouseEvent));
  435. Lock_Data(PendingMouseTail,SizeOf(longint));
  436. Lock_Data(PendingMouseEvents,sizeof(byte));
  437. Lock_Data(MouseButtons,SizeOf(byte));
  438. Lock_Data(MouseWhereX,SizeOf(word));
  439. Lock_Data(MouseWhereY,SizeOf(word));
  440. Lock_Data(drawmousecursor,SizeOf(boolean));
  441. Lock_Data(mouseisvisible,SizeOf(boolean));
  442. Lock_Data(mouselock,SizeOf(boolean));
  443. Lock_Data(videoseg,SizeOf(word));
  444. Lock_Data(dosmemselector,SizeOf(word));
  445. Lock_Data(screenwidth,SizeOf(word));
  446. Lock_Data(OldMouseX,SizeOf(longint));
  447. Lock_Data(OldMouseY,SizeOf(longint));
  448. {$ifdef DEBUG}
  449. Lock_Data(EntryEDI, SizeOf(longint));
  450. Lock_Data(EntryESI, SizeOf(longint));
  451. Lock_Data(EntryDS, SizeOf(word));
  452. Lock_Data(EntryES, SizeOf(word));
  453. Lock_Data(MouseError, SizeOf(longint));
  454. Lock_Data(callcounter, SizeOf(longint));
  455. {$endif DEBUG}
  456. Allocate_mouse_bridge;
  457. FirstMouseInitDone:=true;
  458. end;
  459. If MouseCallBack=Nil then
  460. Mouse_Action($ffff, @MouseInt); { Set masks/interrupt }
  461. drawmousecursor:=false;
  462. mouseisvisible:=false;
  463. if (screenwidth>80) or (screenheight>50) then
  464. DoCustomMouse(true);
  465. ShowMouse;
  466. end;
  467. procedure SysDoneMouse;
  468. begin
  469. HideMouse;
  470. If (MouseCallBack <> Nil) Then
  471. Mouse_Action(0, Nil); { Clear mask/interrupt }
  472. end;
  473. function SysDetectMouse:byte;assembler;
  474. asm
  475. movl $0x200,%eax
  476. movl $0x33,%ebx
  477. int $0x31
  478. movw %cx,%ax
  479. orw %ax,%dx
  480. jz .Lno_mouse
  481. xorl %eax,%eax
  482. pushl %ebp
  483. int $0x33
  484. popl %ebp
  485. orw %ax,%ax
  486. jz .Lno_mouse
  487. movl %ebx,%eax
  488. .Lno_mouse:
  489. end;
  490. procedure SysShowMouse;
  491. begin
  492. if drawmousecursor then
  493. begin
  494. lockmouse;
  495. if not(mouseisvisible) then
  496. begin
  497. oldmousex:=getmousex-1;
  498. oldmousey:=getmousey-1;
  499. mem[videoseg:(((screenwidth*oldmousey)+oldmousex)*2)+1]:=
  500. mem[videoseg:(((screenwidth*oldmousey)+oldmousex)*2)+1] xor $7f;
  501. mouseisvisible:=true;
  502. end;
  503. unlockmouse;
  504. end
  505. else
  506. asm
  507. cmpb $1,MousePresent
  508. jne .LShowMouseExit
  509. movl $1,%eax
  510. pushl %ebp
  511. int $0x33
  512. popl %ebp
  513. .LShowMouseExit:
  514. end;
  515. end;
  516. procedure SysHideMouse;
  517. begin
  518. if drawmousecursor then
  519. begin
  520. lockmouse;
  521. if mouseisvisible then
  522. begin
  523. mouseisvisible:=false;
  524. mem[videoseg:(((screenwidth*oldmousey)+oldmousex)*2)+1]:=
  525. mem[videoseg:(((screenwidth*oldmousey)+oldmousex)*2)+1] xor $7f;
  526. oldmousex:=-1;
  527. oldmousey:=-1;
  528. end;
  529. unlockmouse;
  530. end
  531. else
  532. asm
  533. cmpb $1,MousePresent
  534. jne .LHideMouseExit
  535. movl $2,%eax
  536. pushl %ebp
  537. int $0x33
  538. popl %ebp
  539. .LHideMouseExit:
  540. end;
  541. end;
  542. function SysGetMouseX:word;assembler;
  543. asm
  544. cmpb $1,MousePresent
  545. jne .LGetMouseXError
  546. movl $3,%eax
  547. pushl %ebp
  548. int $0x33
  549. popl %ebp
  550. movzwl %cx,%eax
  551. shrl $3,%eax
  552. incl %eax
  553. ret
  554. .LGetMouseXError:
  555. xorl %eax,%eax
  556. end;
  557. function SysGetMouseY:word;assembler;
  558. asm
  559. cmpb $1,MousePresent
  560. jne .LGetMouseYError
  561. movl $3,%eax
  562. pushl %ebp
  563. int $0x33
  564. popl %ebp
  565. movzwl %dx,%eax
  566. shrl $3,%eax
  567. incl %eax
  568. ret
  569. .LGetMouseYError:
  570. xorl %eax,%eax
  571. end;
  572. function SysGetMouseButtons:word;assembler;
  573. asm
  574. cmpb $1,MousePresent
  575. jne .LGetMouseButtonsError
  576. movl $3,%eax
  577. pushl %ebp
  578. int $0x33
  579. popl %ebp
  580. movw %bx,%ax
  581. ret
  582. .LGetMouseButtonsError:
  583. xorl %eax,%eax
  584. end;
  585. procedure SysSetMouseXY(x,y:word);assembler;
  586. asm
  587. cmpb $1,MousePresent
  588. jne .LSetMouseXYExit
  589. movw x,%cx
  590. movw y,%dx
  591. movl $4,%eax
  592. pushl %ebp
  593. int $0x33
  594. popl %ebp
  595. .LSetMouseXYExit:
  596. end;
  597. Procedure SetMouseXRange (Min,Max:Longint);
  598. begin
  599. If Not(MousePresent) Then Exit;
  600. asm
  601. movl $7,%eax
  602. movl min,%ecx
  603. movl max,%edx
  604. pushl %ebp
  605. int $0x33
  606. popl %ebp
  607. end;
  608. end;
  609. Procedure SetMouseYRange (min,max:Longint);
  610. begin
  611. If Not(MousePresent) Then Exit;
  612. asm
  613. movl $8,%eax
  614. movl min,%ecx
  615. movl max,%edx
  616. pushl %ebp
  617. int $0x33
  618. popl %ebp
  619. end;
  620. end;
  621. procedure DoCustomMouse(b : boolean);
  622. begin
  623. HideMouse;
  624. lockmouse;
  625. oldmousex:=-1;
  626. oldmousey:=-1;
  627. SetMouseXRange(0,(screenwidth-1)*8);
  628. SetMouseYRange(0,(screenheight-1)*8);
  629. if b then
  630. begin
  631. mouseisvisible:=false;
  632. drawmousecursor:=true;
  633. end
  634. else
  635. drawmousecursor:=false;
  636. unlockmouse;
  637. end;
  638. const
  639. LastCallcounter : longint = 0;
  640. procedure SysGetMouseEvent(var MouseEvent: TMouseEvent);
  641. begin
  642. if not MousePresent then
  643. begin
  644. Fillchar(MouseEvent,SizeOf(TMouseEvent),#0);
  645. end;
  646. {$ifdef DEBUG}
  647. if mouseError>0 then
  648. Writeln('Errors in mouse Handler ',MouseError);
  649. {$ifdef EXTMOUSEDEBUG}
  650. if callcounter>LastCallcounter then
  651. Writeln('Number of calls in mouse Handler ',Callcounter);
  652. {$endif EXTMOUSEDEBUG}
  653. LastCallcounter:=Callcounter;
  654. {$endif DEBUG}
  655. repeat until PendingMouseEvents>0;
  656. MouseEvent:=PendingMouseHead^;
  657. inc(PendingMouseHead);
  658. if longint(PendingMouseHead)=longint(@PendingMouseEvent)+sizeof(PendingMouseEvent) then
  659. PendingMouseHead:=@PendingMouseEvent;
  660. dec(PendingMouseEvents);
  661. if (LastMouseEvent.x<>MouseEvent.x) or (LastMouseEvent.y<>MouseEvent.y) then
  662. MouseEvent.Action:=MouseActionMove;
  663. if (LastMouseEvent.Buttons<>MouseEvent.Buttons) then
  664. begin
  665. if (LastMouseEvent.Buttons=0) then
  666. MouseEvent.Action:=MouseActionDown
  667. else
  668. MouseEvent.Action:=MouseActionUp;
  669. end;
  670. LastMouseEvent:=MouseEvent;
  671. end;
  672. Const
  673. SysMouseDriver : TMouseDriver = (
  674. useDefaultQueue : true;
  675. InitDriver : @SysInitMouse;
  676. DoneDriver : @SysDoneMouse;
  677. DetectMouse : @SysDetectMouse;
  678. ShowMouse : @SysShowMouse;
  679. HideMouse : @SysHideMouse;
  680. GetMouseX : @SysGetMouseX;
  681. GetMouseY : @SysGetMouseY;
  682. GetMouseButtons : @SysGetMouseButtons;
  683. SetMouseXY : @SysSetMouseXY;
  684. GetMouseEvent : @SysGetMouseEvent;
  685. PollMouseEvent : Nil;
  686. PutMouseEvent : Nil;
  687. );
  688. Begin
  689. SetMouseDriver(SysMouseDriver);
  690. end.
  691. {
  692. $Log$
  693. Revision 1.4 2001-12-26 21:20:47 peter
  694. * more xp fixes
  695. Revision 1.3 2001/12/26 21:03:56 peter
  696. * merged fixes from 1.0.x
  697. Revision 1.2 2001/09/22 00:01:42 michael
  698. + Merged driver support for mouse from fixbranch
  699. Revision 1.1.2.2 2001/09/21 23:53:48 michael
  700. + Added mouse driver support.
  701. Revision 1.1.2.1 2001/01/30 21:52:01 peter
  702. * moved api utils to rtl
  703. Revision 1.1 2001/01/13 11:03:58 peter
  704. * API 2 RTL commit
  705. }