mouse.pp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794
  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. MOVW %cs:v2prt0_ds_alias,%ax
  201. movw %ax,%es
  202. { ES now has dataseg alias that is never invalid }
  203. {$ifdef DEBUG}
  204. MOVL %EDI,%ES:EntryEDI
  205. MOVL %ESI,%ES:EntryESI
  206. MOVW %DS,%AX
  207. MOVW %AX,%ES:EntryDS
  208. MOVW %ES,%AX
  209. MOVW %AX,%ES:EntryES
  210. {$endif DEBUG}
  211. { movw %cs:v2prt0_ds_alias,%ax v2prt0 is not locked !!
  212. movw %ax,%ds
  213. movw %ax,%es }
  214. PUSH %ES; { Push data seg }
  215. POP %DS; { Load data seg }
  216. {$ifdef DEBUG}
  217. incl callcounter
  218. CMPL $ACTIONREGS,%edi
  219. JE .L_ActionRegsOK
  220. INCL MouseError
  221. JMP .L_NoCallBack
  222. .L_ActionRegsOK:
  223. {$endif DEBUG}
  224. MOVL MOUSECALLBACK, %EAX; { Fetch callback addr }
  225. CMPL $0, %EAX; { Check for nil ptr }
  226. JZ .L_NoCallBack; { Ignore if nil }
  227. MOVL %EDI,%EAX; { %EAX = @actionregs }
  228. MOVL (%EAX), %EDI; { EDI from actionregs }
  229. MOVL 4(%EAX), %ESI; { ESI from actionregs }
  230. MOVL 16(%EAX), %EBX; { EBX from actionregs }
  231. MOVL 20(%EAX), %EDX; { EDX from actionregs }
  232. MOVL 24(%EAX), %ECX; { ECX from actionregs }
  233. MOVL 28(%EAX), %EAX; { EAX from actionregs }
  234. CALL *MOUSECALLBACK; { Call callback proc }
  235. .L_NoCallBack:
  236. popl %edx;
  237. popl %ecx;
  238. popl %ebx;
  239. POPL %ESI; { Recover register }
  240. POPL %EDI; { Recover register }
  241. POP %FS; { Restore FS register }
  242. POP %DS; { Restore DS register }
  243. POP %ES; { Restore ES register }
  244. movw %es,%ax
  245. cmpw $0,%ax
  246. jne .Lesisok
  247. { ; caution : ds is not the selector for our data !! }
  248. MOVW %cs:v2prt0_ds_alias,%ax
  249. movw %ax,%es
  250. .Lesisok:
  251. lsl %eax,%eax
  252. cmpl %edi,%eax
  253. ja .Ldontzeroedi
  254. movzwl %di,%edi
  255. .Ldontzeroedi:
  256. movw %ds,%ax
  257. lsl %eax,%eax
  258. cmpl %esi,%eax
  259. ja .Lsimplecopy
  260. movzwl %si,%eax
  261. jmp .Lcopyend
  262. .Lsimplecopy:
  263. movl %esi,%eax
  264. .Lcopyend:
  265. MOVL %ds:(%Eax), %EAX
  266. MOVL %EAX, %ES:42(%EDI) { Set as return addr }
  267. ADDW $4, %ES:46(%EDI) { adjust stack }
  268. popl %eax
  269. IRET { Interrupt return }
  270. END;
  271. Function Allocate_mouse_bridge : boolean;
  272. var
  273. error : word;
  274. begin
  275. ASM
  276. LEAL ACTIONREGS, %EDI; { Addr of actionregs }
  277. LEAL MOUSE_TRAP, %ESI; { Procedure address }
  278. CMPB $0, UnderNT
  279. JZ .LGo32
  280. LEAL MOUSE_TRAP_NT, %ESI; { Procedure address }
  281. .LGo32:
  282. PUSH %DS; { Save DS segment }
  283. PUSH %ES; { Save ES segment }
  284. MOVW v2prt0_ds_alias,%ES; { ES now has dataseg alias that is never invalid }
  285. PUSH %CS;
  286. POP %DS; { DS now has codeseg }
  287. MOVW $0x303, %AX; { Function id }
  288. INT $0x31; { Call DPMI bridge }
  289. JNC .L_call_ok; { Branch if ok }
  290. POP %ES; { Restore ES segment }
  291. POP %DS; { Restore DS segment }
  292. MOVW $0,REALSEG;
  293. MOVW $0,REALOFS;
  294. JMP .L_exit
  295. .L_call_ok:
  296. POP %ES; { Restore ES segment }
  297. POP %DS; { Restore DS segment }
  298. MOVW %CX,REALSEG; { Transfer real seg }
  299. MOVW %DX,REALOFS; { Transfer real ofs }
  300. MOVW $0, %AX; { Force error to zero }
  301. .L_exit:
  302. MOVW %AX, ERROR; { Return error state }
  303. END;
  304. Allocate_mouse_bridge:=error=0;
  305. end;
  306. Procedure Release_mouse_bridge;
  307. begin
  308. ASM
  309. MOVW $0x304, %AX; { Set function id }
  310. MOVW REALSEG, %CX; { Bridged real seg }
  311. MOVW REALOFS, %DX; { Bridged real ofs }
  312. INT $0x31; { Release bridge }
  313. MOVW $0,REALSEG;
  314. MOVW $0,REALOFS;
  315. END;
  316. end;
  317. PROCEDURE Mouse_Action (Mask : Word; P : Pointer);
  318. VAR
  319. Error : Word;
  320. Rg : TRealRegs;
  321. BEGIN
  322. Error := 0; { Preset no error }
  323. If (P <> MouseCallBack) or (Mask<>CurrentMask) Then { Check func different }
  324. Begin
  325. { Remove old calback }
  326. If (CurrentMask <> 0) Then
  327. Begin
  328. Rg.AX := 12; { Function id }
  329. Rg.CX := 0; { Zero mask register }
  330. Rg.ES := 0; { Zero proc seg }
  331. Rg.DX := 0; { Zero proc ofs }
  332. RealIntr($33, Rg); { Stop INT 33 callback }
  333. End;
  334. if RealSeg=0 then
  335. error:=1;
  336. { test addresses for Windows NT }
  337. if (longint(@actionregs)>$ffff) {or
  338. (longint(@mouse_trap)>$ffff)} then
  339. begin
  340. error:=1;
  341. end
  342. else If (P = Nil) Then
  343. Begin
  344. Mask := 0; { Zero mask register }
  345. End;
  346. If (Error = 0) Then
  347. Begin
  348. MouseCallback := P; { Set call back addr }
  349. if Mask<>0 then
  350. begin
  351. Rg.AX := 12; { Set function id }
  352. Rg.CX := Mask; { Set mask register }
  353. If Mask<>0 then
  354. begin
  355. Rg.ES := RealSeg; { Real mode segment }
  356. Rg.DX := RealOfs; { Real mode offset }
  357. end
  358. else
  359. begin
  360. Rg.ES:=0;
  361. Rg.DX:=0;
  362. end;
  363. RealIntr($33, Rg); { Set interrupt 33 }
  364. end;
  365. CurrentMask:=Mask;
  366. End;
  367. End;
  368. If (Error <> 0) Then
  369. Begin
  370. Writeln('GO32V2 mouse handler set failed !!');
  371. ReadLn; { Wait for user to see }
  372. End;
  373. END;
  374. { We need to remove the mouse callback before exiting !! PM }
  375. const StoredExit : Pointer = Nil;
  376. FirstMouseInitDone : boolean = false;
  377. procedure MouseSafeExit;
  378. begin
  379. ExitProc:=StoredExit;
  380. if MouseCallBack<>Nil then
  381. Mouse_Action(0, Nil);
  382. if not FirstMouseInitDone then
  383. exit;
  384. FirstMouseInitDone:=false;
  385. Unlock_Code(Pointer(@Mouse_Trap), 400); { Release trap code }
  386. Unlock_Code(Pointer(@Mouse_Trap_NT), 400); { Release trap code }
  387. Unlock_Code(Pointer(@MouseInt), 400); { Lock MouseInt code }
  388. Unlock_Data(ActionRegs, SizeOf(TRealRegs)); { Release registers }
  389. UnLock_Data(MouseCallBack,SizeOf(Pointer));
  390. { unlock Mouse Queue and related stuff ! }
  391. Unlock_Data(PendingMouseEvent,
  392. MouseEventBufSize*Sizeof(TMouseEvent));
  393. Unlock_Data(PendingMouseTail,SizeOf(longint));
  394. Unlock_Data(PendingMouseEvents,sizeof(byte));
  395. Unlock_Data(MouseButtons,SizeOf(byte));
  396. Unlock_Data(MouseWhereX,SizeOf(word));
  397. Unlock_Data(MouseWhereY,SizeOf(word));
  398. Unlock_Data(drawmousecursor,SizeOf(boolean));
  399. Unlock_Data(mouseisvisible,SizeOf(boolean));
  400. Unlock_Data(mouselock,SizeOf(boolean));
  401. Unlock_Data(videoseg,SizeOf(word));
  402. Unlock_Data(dosmemselector,SizeOf(word));
  403. Unlock_Data(screenwidth,SizeOf(word));
  404. Unlock_Data(OldMouseX,SizeOf(longint));
  405. Unlock_Data(OldMouseY,SizeOf(longint));
  406. {$ifdef DEBUG}
  407. Unlock_Data(EntryEDI, SizeOf(longint));
  408. Unlock_Data(EntryESI, SizeOf(longint));
  409. Unlock_Data(EntryDS, SizeOf(word));
  410. Unlock_Data(EntryES, SizeOf(word));
  411. Unlock_Data(MouseError, SizeOf(longint));
  412. Unlock_Data(callcounter, SizeOf(longint));
  413. {$endif DEBUG}
  414. Release_mouse_bridge;
  415. end;
  416. function RunningUnderWINNT: boolean;
  417. var r: trealregs;
  418. begin
  419. fillchar(r,sizeof(r),0);
  420. r.ax:=$3306;
  421. realintr($21,r);
  422. RunningUnderWINNT:=(r.bx=$3205);
  423. end;
  424. procedure SysInitMouse;
  425. begin
  426. UnderNT:=RunningUnderWINNT;
  427. if not MousePresent then
  428. begin
  429. if DetectMouse=0 then
  430. begin
  431. Writeln('No mouse driver found ');
  432. exit;
  433. end
  434. else
  435. MousePresent:=true;
  436. end;
  437. { don't do this twice !! PM }
  438. If not FirstMouseInitDone then
  439. begin
  440. StoredExit:=ExitProc;
  441. ExitProc:=@MouseSafeExit;
  442. Lock_Code(Pointer(@Mouse_Trap), 400); { Lock trap code }
  443. Lock_Code(Pointer(@Mouse_Trap_NT), 400); { Lock trap code }
  444. Lock_Code(Pointer(@MouseInt), 400); { Lock MouseInt code }
  445. Lock_Data(ActionRegs, SizeOf(TRealRegs)); { Lock registers }
  446. Lock_Data(MouseCallBack, SizeOf(pointer));
  447. { lock Mouse Queue and related stuff ! }
  448. Lock_Data(PendingMouseEvent,
  449. MouseEventBufSize*Sizeof(TMouseEvent));
  450. Lock_Data(PendingMouseTail,SizeOf(longint));
  451. Lock_Data(PendingMouseEvents,sizeof(byte));
  452. Lock_Data(MouseButtons,SizeOf(byte));
  453. Lock_Data(MouseWhereX,SizeOf(word));
  454. Lock_Data(MouseWhereY,SizeOf(word));
  455. Lock_Data(drawmousecursor,SizeOf(boolean));
  456. Lock_Data(mouseisvisible,SizeOf(boolean));
  457. Lock_Data(mouselock,SizeOf(boolean));
  458. Lock_Data(videoseg,SizeOf(word));
  459. Lock_Data(dosmemselector,SizeOf(word));
  460. Lock_Data(screenwidth,SizeOf(word));
  461. Lock_Data(OldMouseX,SizeOf(longint));
  462. Lock_Data(OldMouseY,SizeOf(longint));
  463. {$ifdef DEBUG}
  464. Lock_Data(EntryEDI, SizeOf(longint));
  465. Lock_Data(EntryESI, SizeOf(longint));
  466. Lock_Data(EntryDS, SizeOf(word));
  467. Lock_Data(EntryES, SizeOf(word));
  468. Lock_Data(MouseError, SizeOf(longint));
  469. Lock_Data(callcounter, SizeOf(longint));
  470. {$endif DEBUG}
  471. Allocate_mouse_bridge;
  472. FirstMouseInitDone:=true;
  473. end;
  474. If MouseCallBack=Nil then
  475. Mouse_Action($ffff, @MouseInt); { Set masks/interrupt }
  476. drawmousecursor:=false;
  477. mouseisvisible:=false;
  478. if (screenwidth>80) or (screenheight>50) then
  479. DoCustomMouse(true);
  480. ShowMouse;
  481. end;
  482. procedure SysDoneMouse;
  483. begin
  484. HideMouse;
  485. If (MouseCallBack <> Nil) Then
  486. Mouse_Action(0, Nil); { Clear mask/interrupt }
  487. end;
  488. function SysDetectMouse:byte;assembler;
  489. asm
  490. movl $0x200,%eax
  491. movl $0x33,%ebx
  492. int $0x31
  493. movw %cx,%ax
  494. orw %ax,%dx
  495. jz .Lno_mouse
  496. xorl %eax,%eax
  497. pushl %ebp
  498. int $0x33
  499. popl %ebp
  500. orw %ax,%ax
  501. jz .Lno_mouse
  502. movl %ebx,%eax
  503. .Lno_mouse:
  504. end;
  505. procedure SysShowMouse;
  506. begin
  507. if drawmousecursor then
  508. begin
  509. lockmouse;
  510. if not(mouseisvisible) then
  511. begin
  512. oldmousex:=getmousex-1;
  513. oldmousey:=getmousey-1;
  514. mem[videoseg:(((screenwidth*oldmousey)+oldmousex)*2)+1]:=
  515. mem[videoseg:(((screenwidth*oldmousey)+oldmousex)*2)+1] xor $7f;
  516. mouseisvisible:=true;
  517. end;
  518. unlockmouse;
  519. end
  520. else
  521. asm
  522. cmpb $1,MousePresent
  523. jne .LShowMouseExit
  524. movl $1,%eax
  525. pushl %ebp
  526. int $0x33
  527. popl %ebp
  528. .LShowMouseExit:
  529. end;
  530. end;
  531. procedure SysHideMouse;
  532. begin
  533. if drawmousecursor then
  534. begin
  535. lockmouse;
  536. if mouseisvisible then
  537. begin
  538. mouseisvisible:=false;
  539. mem[videoseg:(((screenwidth*oldmousey)+oldmousex)*2)+1]:=
  540. mem[videoseg:(((screenwidth*oldmousey)+oldmousex)*2)+1] xor $7f;
  541. oldmousex:=-1;
  542. oldmousey:=-1;
  543. end;
  544. unlockmouse;
  545. end
  546. else
  547. asm
  548. cmpb $1,MousePresent
  549. jne .LHideMouseExit
  550. movl $2,%eax
  551. pushl %ebp
  552. int $0x33
  553. popl %ebp
  554. .LHideMouseExit:
  555. end;
  556. end;
  557. function SysGetMouseX:word;assembler;
  558. asm
  559. cmpb $1,MousePresent
  560. jne .LGetMouseXError
  561. movl $3,%eax
  562. pushl %ebp
  563. int $0x33
  564. popl %ebp
  565. movzwl %cx,%eax
  566. shrl $3,%eax
  567. incl %eax
  568. ret
  569. .LGetMouseXError:
  570. xorl %eax,%eax
  571. end;
  572. function SysGetMouseY:word;assembler;
  573. asm
  574. cmpb $1,MousePresent
  575. jne .LGetMouseYError
  576. movl $3,%eax
  577. pushl %ebp
  578. int $0x33
  579. popl %ebp
  580. movzwl %dx,%eax
  581. shrl $3,%eax
  582. incl %eax
  583. ret
  584. .LGetMouseYError:
  585. xorl %eax,%eax
  586. end;
  587. function SysGetMouseButtons:word;assembler;
  588. asm
  589. cmpb $1,MousePresent
  590. jne .LGetMouseButtonsError
  591. movl $3,%eax
  592. pushl %ebp
  593. int $0x33
  594. popl %ebp
  595. movw %bx,%ax
  596. ret
  597. .LGetMouseButtonsError:
  598. xorl %eax,%eax
  599. end;
  600. procedure SysSetMouseXY(x,y:word);assembler;
  601. asm
  602. cmpb $1,MousePresent
  603. jne .LSetMouseXYExit
  604. movw x,%cx
  605. movw y,%dx
  606. movl $4,%eax
  607. pushl %ebp
  608. int $0x33
  609. popl %ebp
  610. .LSetMouseXYExit:
  611. end;
  612. Procedure SetMouseXRange (Min,Max:Longint);
  613. begin
  614. If Not(MousePresent) Then Exit;
  615. asm
  616. movl $7,%eax
  617. movl min,%ecx
  618. movl max,%edx
  619. pushl %ebp
  620. int $0x33
  621. popl %ebp
  622. end;
  623. end;
  624. Procedure SetMouseYRange (min,max:Longint);
  625. begin
  626. If Not(MousePresent) Then Exit;
  627. asm
  628. movl $8,%eax
  629. movl min,%ecx
  630. movl max,%edx
  631. pushl %ebp
  632. int $0x33
  633. popl %ebp
  634. end;
  635. end;
  636. procedure DoCustomMouse(b : boolean);
  637. begin
  638. HideMouse;
  639. lockmouse;
  640. oldmousex:=-1;
  641. oldmousey:=-1;
  642. SetMouseXRange(0,(screenwidth-1)*8);
  643. SetMouseYRange(0,(screenheight-1)*8);
  644. if b then
  645. begin
  646. mouseisvisible:=false;
  647. drawmousecursor:=true;
  648. end
  649. else
  650. drawmousecursor:=false;
  651. unlockmouse;
  652. end;
  653. const
  654. LastCallcounter : longint = 0;
  655. procedure SysGetMouseEvent(var MouseEvent: TMouseEvent);
  656. begin
  657. if not MousePresent then
  658. begin
  659. Fillchar(MouseEvent,SizeOf(TMouseEvent),#0);
  660. end;
  661. {$ifdef DEBUG}
  662. if mouseError>0 then
  663. Writeln('Errors in mouse Handler ',MouseError);
  664. {$ifdef EXTMOUSEDEBUG}
  665. if callcounter>LastCallcounter then
  666. Writeln('Number of calls in mouse Handler ',Callcounter);
  667. {$endif EXTMOUSEDEBUG}
  668. LastCallcounter:=Callcounter;
  669. {$endif DEBUG}
  670. repeat until PendingMouseEvents>0;
  671. MouseEvent:=PendingMouseHead^;
  672. inc(PendingMouseHead);
  673. if longint(PendingMouseHead)=longint(@PendingMouseEvent)+sizeof(PendingMouseEvent) then
  674. PendingMouseHead:=@PendingMouseEvent;
  675. dec(PendingMouseEvents);
  676. if (LastMouseEvent.x<>MouseEvent.x) or (LastMouseEvent.y<>MouseEvent.y) then
  677. MouseEvent.Action:=MouseActionMove;
  678. if (LastMouseEvent.Buttons<>MouseEvent.Buttons) then
  679. begin
  680. if (LastMouseEvent.Buttons=0) then
  681. MouseEvent.Action:=MouseActionDown
  682. else
  683. MouseEvent.Action:=MouseActionUp;
  684. end;
  685. LastMouseEvent:=MouseEvent;
  686. end;
  687. Const
  688. SysMouseDriver : TMouseDriver = (
  689. useDefaultQueue : true;
  690. InitDriver : @SysInitMouse;
  691. DoneDriver : @SysDoneMouse;
  692. DetectMouse : @SysDetectMouse;
  693. ShowMouse : @SysShowMouse;
  694. HideMouse : @SysHideMouse;
  695. GetMouseX : @SysGetMouseX;
  696. GetMouseY : @SysGetMouseY;
  697. GetMouseButtons : @SysGetMouseButtons;
  698. SetMouseXY : @SysSetMouseXY;
  699. GetMouseEvent : @SysGetMouseEvent;
  700. PollMouseEvent : Nil;
  701. PutMouseEvent : Nil;
  702. );
  703. Begin
  704. SetMouseDriver(SysMouseDriver);
  705. end.
  706. {
  707. $Log$
  708. Revision 1.5 2002-01-19 11:57:55 peter
  709. * merged fixes
  710. Revision 1.4 2001/12/26 21:20:47 peter
  711. * more xp fixes
  712. Revision 1.3 2001/12/26 21:03:56 peter
  713. * merged fixes from 1.0.x
  714. Revision 1.2 2001/09/22 00:01:42 michael
  715. + Merged driver support for mouse from fixbranch
  716. Revision 1.1.2.2 2001/09/21 23:53:48 michael
  717. + Added mouse driver support.
  718. Revision 1.1.2.1 2001/01/30 21:52:01 peter
  719. * moved api utils to rtl
  720. Revision 1.1 2001/01/13 11:03:58 peter
  721. * API 2 RTL commit
  722. }