{**********************************************************************
Copyright (C) 2009 by Salvatore Licciardi

Web http://www.webalice.it/turylicciardi    eMail turylicciardi@tiscali.it

 This program is free software: you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free Software
 Foundation, version 3 of the License.
 This program is distributed in the hope  that it will be useful , but WITHOUT
 ANY WARRANTY without even the implied warranty  of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.
 See the GNU General Public License for more details. You should have received
 a copy of the GNU General Public License along with this program. If not, see
 http://www.gnu.org/licenses/

 **********************************************************************}

{ this unit is for FreePascal 2.0.x
  this unit is for Go32v2 (DOS) , Win32 , OS/2 target

  written by: Salvatore Licciardi
  WWW page  : www.webalice.it/turylicciardi
  E-Mail    : turylicciardi@tiscali.it
  this file : www.webalice.it/turylicciardi/prog/mclick.zip
              (MClick22.pas, Click_.pas, Ex_Mck22.pas)
  version   : 2.2.0  2005/06/xx
}

unit MClick22;

interface
uses   {$ifdef Go32v2}
       MsMouse,
       {$else}
       Mouse,
       {$endif}
       Dos,Click_;

{ Key:  0: None, 1:Left,  2: Right,  bx=3: Center }
type More_Click=Object
               public
                constructor  Init;
                destructor   Destroy;
                function  Double_Click:boolean;
                function  Get_First_X:word;
                function  Get_First_Y:word;
                function  Get_Last_X:word;
                function  Get_Last_Y:word;
                function  Get_First_Button:char;
                function  Get_Last_Button:char;
                function  Get_Delay_Click:word;
                function  Mouse_Down_Central(var mox,moy,key:byte):boolean;
                function  Mouse_Down_R(var mox,moy,key:byte):boolean;
                function  Mouse_Down_L(var mox,moy,key:byte):boolean;
                function  Mouse_Up_R(var mox,moy,key:byte):boolean;
                function  Mouse_Up_L(var mox,moy,key:byte):boolean;
                function  Get_Last_Multi_Button:char;
                function  Move:boolean;                   // ver 2.1.0
                function  More_Click(n:longint):boolean;  // ver 2.0.0
                function  Get_Num_Click_Max:word;         // ver 2.0.0
                procedure Set_Num_Click_Max(n:word);      // ver 2.0.0
                procedure Set_Delay_Click(delay:word);    // tra un click e l'altro
                procedure Empty_Mouse;
                procedure Set_Mancino(mancino_:boolean);  // ver 2.2.0
                function  Get_Mancino():boolean;          // ver 2.2.0
                function  Mouse_Down(var mox,moy,key:byte):boolean; // ver 2.2.0
                function  Mouse_Up(var mox,moy,key:byte):boolean;   // ver 2.2.0

               private
                Last_Multi_Button:char;
                time_mouse: array of time_click;  // Down,Up,Down ... si parte dall'elemento 1
                capture_x,capture_y:byte;
                delay_click:word;
                get_num_click_chk:longint;
                mancino:boolean;  // ver 2.20
                function  First_Position:longint;
                function  Time100:longint;
                procedure Set_Auto_Delay_Click;   // ver 2.0.0
                procedure Capture_Time(button,direction:char);
               end;

implementation

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

destructor  More_Click.Destroy;
begin
setlength(time_mouse,0);
// DoneMouse;  Lo deve eseguire solo MOUSE, perche' puo' causare crash in altri oggetti di tipo More_CLick
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

function  More_Click.first_position:longint;
begin
{$ifdef Go32v2}
 exit( length(time_mouse)-(get_num_click_chk*2-1) );
{$else}
 exit( length(time_mouse)-get_num_click_chk );
{$endif}
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

function  More_Click.Get_Num_Click_Max:word;
begin
{$ifdef Go32v2}
 exit(length(time_mouse) div 2);
{$else}
 exit(length(time_mouse)-1);
{$endif}
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

procedure More_Click.Set_Num_Click_Max(n:word);
begin
if n<2 then Exit;
{$ifdef Go32v2}
 setlength(time_mouse,n*2);
{$else}
 setlength(time_mouse,n+1);
{$endif}
Set_Auto_Delay_Click;
Empty_Mouse;
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

function More_Click.Time100:longint;
var h,m,s,cs:word;
begin
GetTime(h,m,s,cs);
Time100:=(h*60*60+m*60+s)*100+cs;
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

procedure  More_Click.Set_Delay_Click(delay:word); // tra un click e l'altro
begin
delay_click:=delay;
Set_Auto_Delay_Click;
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

function   More_Click.Get_Delay_Click:word;
begin
Get_Delay_Click:=delay_click;
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

procedure  More_Click.Set_Auto_Delay_Click;
const default_delay=20;
begin
delay_click:=default_delay*(Get_Num_Click_Max-1);
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

constructor  More_Click.init;
const default_num_click=2;
begin
Set_Num_Click_Max(default_num_click);
get_num_click_chk:=default_num_click;
delay_click:=20*(Get_Num_Click_Max-1);
mancino:=false;
Empty_Mouse;
{$ifdef Go32v2}
if not mousefound then       // MouseFound solo per Go32v2
{$endif}
                  InitMouse;
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

procedure More_Click.Empty_Mouse;
var i:longint;
begin
for i:=1 to length(time_mouse)-1 do
    begin
    time_mouse[i].x:=255;
    time_mouse[i].y:=255;
    time_mouse[i].direction:=char(i);
    time_mouse[i].button:=char(i);
    time_mouse[i].t:=-10000+i*1000;
    end;
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

function More_Click.Get_Last_Multi_Button:char;
begin
Get_Last_Multi_Button:=Last_Multi_Button;
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

function More_Click.Double_Click:boolean;
begin
exit(More_Click(2));
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

function More_Click.More_Click(n:longint):boolean;
var i:longint;
begin
get_num_click_chk:=n;
More_Click:=false;
Last_Multi_Button:=' ';
if (n<2) then Exit;
if n>get_num_click_Max then
                       begin
                       Set_Num_Click_Max(word(n));
                       get_num_click_chk:=n;
                       end;
for i:=first_position+1 to length(time_mouse)-1 do
    begin
    if (time_mouse[first_position].x<>time_mouse[i].x) or  // stessa X
       (time_mouse[first_position].y<>time_mouse[i].y) or  // stessa Y
       (time_mouse[first_position].button<>time_mouse[i].button) then Exit; // stesso tasto
    end;

for i:=first_position to length(time_mouse)-1 do
    {$ifdef Go32v2}
    if (i mod 2)=0 then   // posizione pari deve essere U
                    if time_mouse[i].direction<>'U' then Exit
                                                    else
                   else   // posizione dispari deve essere D
    {$endif}
                    if time_mouse[i].direction<>'D' then Exit;

if (abs(time_mouse[length(time_mouse)-1].t-time_mouse[first_position].t)<delay_click) then
         begin
         Last_Multi_Button:=time_mouse[length(time_mouse)-1].button;
         More_Click:=true;
         end;
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

function  More_Click.Get_First_X:word;
begin
Get_First_X:=time_mouse[first_position].x;
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

function  More_Click.Get_First_Y:word;
begin
Get_First_Y:=time_mouse[first_position].Y;
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

function  More_Click.Get_Last_X:word;
begin
Get_Last_X:=time_mouse[length(time_mouse)-1].x;
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

function  More_Click.Get_Last_Y:word;
begin
Get_Last_Y:=time_mouse[length(time_mouse)-1].y;
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

function  More_Click.Get_Last_Button:char;
begin
Get_Last_Button:=time_mouse[length(time_mouse)-1].button;
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

function  More_Click.Get_First_Button:char;
begin
Get_First_Button:=time_mouse[first_position].button;
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

procedure More_Click.Capture_Time(button,direction:char);
var i:longint;
begin
{$ifdef Go32v2}
if (direction<>time_mouse[length(time_mouse)-1].direction) or
   (button<>time_mouse[length(time_mouse)-1].button) then
{$endif}
       begin
       for i:=2 to length(time_mouse)-1 do time_mouse[i-1]:=time_mouse[i];
       time_mouse[length(time_mouse)-1].direction:=direction;
       end;
time_mouse[length(time_mouse)-1].button:=button;
time_mouse[length(time_mouse)-1].x:=capture_x;
time_mouse[length(time_mouse)-1].y:=capture_y;
time_mouse[length(time_mouse)-1].t:=time100;
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

function  More_Click.Mouse_Down_R(var mox,moy,key:byte):boolean;
{$ifdef go32v2}
var reg:registers;
begin
reg.ax:=3;
intr($33,reg);
mox:=(reg.cx div 8)+1;
moy:=(reg.dx div 8)+1;
key:=reg.bx;      { bx=0: None, bx=1: L,  bx=2: R,  bx=3: C }
if key=2 then
           begin
           capture_x:=mox;
           capture_y:=moy;
           end
          else
           begin
           Mouse_Down_R:=false;
           Exit;
           end;
Mouse_Down_R:=(key=2);
if key=2 then Capture_Time('R','D');
end;
{$else}
Var Event: TMouseEvent;
begin
If not PollMouseEvent(Event) then
                             begin
                             mox:=byte(getMouseX+1);
                             moy:=byte(getMouseY+1);
                             Exit(false);
                             end;
GetMouseEvent(Event);
if ( Event.Buttons=MouseRightbutton ) and ( Event.Action=MouseActionDown ) then
    begin
    capture_x:=byte(getMouseX+1);
    capture_y:=byte(getMouseY+1);
    mox:=capture_x;
    moy:=capture_y;
    key:=2;
    Mouse_Down_R:=true;
    Capture_Time('R','D');
    end
   else
    begin
    Mouse_Down_R:=false;
    key:=0;
    end;
end;
{$endif}

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

function  More_Click.Mouse_Down_L(var mox,moy,key:byte):boolean;
{$ifdef go32v2}
var reg:registers;
begin
reg.ax:=3;
intr($33,reg);
mox:=(reg.cx div 8) +1;
moy:=(reg.dx div 8) +1;
key:=reg.bx;      { bx=0: None, bx=1: L,  bx=2: R,  bx=3: C }
if key=1 then
           begin
           capture_x:=mox;
           capture_y:=moy;
           end
          else
           begin
           Mouse_Down_L:=false;
           Exit;
           end;
Mouse_Down_L:=(key=1);
if key=1 then Capture_Time('L','D');
end;
{$else}
Var Event: TMouseEvent;
begin
If not PollMouseEvent(Event) then
                             begin
                             mox:=byte(getMouseX+1);
                             moy:=byte(getMouseY+1);
                             Exit(false);
                             end;
GetMouseEvent(Event);
if ( Event.Buttons=MouseLeftbutton ) and ( Event.Action=MouseActionDown ) then
    begin
    capture_x:=byte(getMouseX+1);
    capture_y:=byte(getMouseY+1);
    mox:=capture_x;
    moy:=capture_y;
    key:=1;
    Mouse_Down_L:=true;
    Capture_Time('L','D');
    end
   else
    begin
    Mouse_Down_L:=false;
    key:=0;
    end;
end;
{$endif}

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

function  More_Click.Mouse_Down_Central(var mox,moy,key:byte):boolean;
{$ifdef go32v2}
var reg:registers;
begin
reg.ax:=3;
intr($33,reg);
mox:=(reg.cx div 8) +1;
moy:=(reg.dx div 8) +1;
key:=reg.bx;      { bx=0: None, bx=1: L,  bx=2: R,  bx=3: C }
if key=3 then
           begin
           capture_x:=mox;
           capture_y:=moy;
           end
          else
           begin
           Mouse_Down_Central:=false;
           Exit;
           end;
Mouse_Down_Central:=(key=3);
if key=3 then Capture_Time('C','D');
end;
{$else}
Var Event: TMouseEvent;
begin
If not PollMouseEvent(Event) then
                             begin
                             mox:=byte(getMouseX+1);
                             moy:=byte(getMouseY+1);
                             Exit(false);
                             end;
GetMouseEvent(Event);
if ( Event.Buttons=MouseMiddlebutton ) and ( Event.Action=MouseActionDown ) then
    begin
    capture_x:=byte(getMouseX+1);
    capture_y:=byte(getMouseY+1);
    mox:=capture_x;
    moy:=capture_y;
    key:=3;
    Mouse_Down_Central:=true;
    Capture_Time('C','D');
    end
   else
    begin
    Mouse_Down_Central:=false;
    key:=0;
    end;
end;
{$endif}

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

function  More_Click.Mouse_Up_L(var mox,moy,key:byte):boolean;
{$ifdef go32v2}
var reg:registers;
begin
reg.bx:=0;     { bx=0: L,  bx=1: R }
reg.ax:=6;
intr($33,reg);
mox:=reg.cx div 8 +1;
moy:=reg.dx div 8 +1;
key:=reg.bx;
if key=1 then Capture_Time('L','U');
Mouse_Up_L:=(key=1);
end;
{$else}
Var Event: TMouseEvent;
begin
If not PollMouseEvent(Event) then
                             begin
                             mox:=byte(getMouseX+1);
                             moy:=byte(getMouseY+1);
                             Exit(false);
                             end;
GetMouseEvent(Event);
if ( Event.Buttons=MouseLeftbutton ) and ( Event.Action=MouseActionUp ) then
    begin
    capture_x:=byte(getMouseX+1);
    capture_y:=byte(getMouseY+1);
    mox:=capture_x;
    moy:=capture_y;
    key:=1;
    Mouse_Up_L:=true;
    Capture_Time('L','U');
    end
   else
    begin
    Mouse_Up_L:=false;
    key:=0;
    end;
end;
{$endif}

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

function  More_Click.Mouse_Up_R(var mox,moy,key:byte):boolean;
{$ifdef go32v2}
var reg:registers;
begin
reg.bx:=1;     { bx=0: L,  bx=1: R }
reg.ax:=6;
intr($33,reg);
moy:=reg.dx div 8 +1;
mox:=reg.cx div 8 +1;
key:=reg.bx;
if key=1 then Capture_Time('R','U');
Mouse_Up_R:=(key=1);
end;
{$else}
Var Event: TMouseEvent;
begin
If not PollMouseEvent(Event) then
                             begin
                             mox:=byte(getMouseX+1);
                             moy:=byte(getMouseY+1);
                             Exit(false);
                             end;
GetMouseEvent(Event);
if ( Event.Buttons=MouseRightbutton ) and ( Event.Action=MouseActionUp ) then
    begin
    capture_x:=byte(getMouseX+1);
    capture_y:=byte(getMouseY+1);
    mox:=capture_x;
    moy:=capture_y;
    key:=1;
    Mouse_Up_R:=true;
    Capture_Time('R','U');
    end
   else
    begin
    Mouse_Up_R:=false;
    key:=0;
    end;
end;
{$endif}

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

function  More_Click.Move:boolean;                   // ver 2.1.0
const original_x:longint=-1;    // variabile locale globalizzata
const original_y:longint=-1;    // variabile locale globalizzata
var x,y{$ifdef Go32v2},state{$endif}:longint;
begin
{$ifdef Go32v2}
 getMouseState(x,y,state);
{$else}
 x:=getMouseX;
 y:=getMouseY;
{$endif}
move:=(original_x<>x)or(original_y<>y);
original_x:=x;
original_y:=y;
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

function  More_Click.Mouse_Down(var mox,moy,key:byte):boolean; // ver 2.2.0
begin
if mancino then Mouse_Down:=Mouse_Down_R(mox,moy,key)
           else Mouse_Down:=Mouse_Down_L(mox,moy,key);
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

function  More_Click.Mouse_Up(var mox,moy,key:byte):boolean;   // ver 2.2.0
begin
if mancino then Mouse_Up:=Mouse_Up_R(mox,moy,key)
           else Mouse_Up:=Mouse_Up_L(mox,moy,key);
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

procedure More_Click.Set_Mancino(mancino_:boolean);   // ver 2.2.0
begin
mancino:=mancino_;
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

function  More_Click.Get_Mancino():boolean;          // ver 2.2.0
begin
exit(mancino);
end;

{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}

begin
end.
