Source file: /~heha/messtech/d2s.zip/SRC/WUTILS32.PAS

unit wutils32;
interface
uses Windows,Messages,ShellApi;
const
 StdMBoxTitle: PChar=nil;
 MB_Sound = $0080;
 File_Share_Delete=4;
function vMBox(WndParent:HWnd; ID,style:Word; var p):Integer; stdcall;
function MBox0(WndParent:HWnd; ID,style:Word):Integer; cdecl;
function MBox1(WndParent:HWnd; ID,style:Word; S1:PChar):Integer; cdecl;
function MBox2(WndParent:HWnd; ID,style:Word; S1,S2:PChar):Integer; cdecl;
function MBox3(WndParent:HWnd; ID,style:Word; S1,S2,S3:PChar):Integer; cdecl;
function MBox4(WndParent:HWnd; ID,style:Word; S1,S2,S3,S4:PChar):Integer; cdecl;
function MBox5(WndParent:HWnd; ID,style:Word; S1,S2,S3,S4,S5:PChar):Integer; cdecl;
function MBox6(WndParent:HWnd; ID,style:Word; S1,S2,S3,S4,S5,S6:PChar):Integer; cdecl;
function MBox7(WndParent:HWnd; ID,style:Word; S1,S2,S3,S4,S5,S6,S7:PChar):Integer; cdecl;
function MBox8(WndParent:HWnd; ID,style:Word; S1,S2,S3,S4,S5,S6,S7,S8:PChar):Integer; cdecl;
//Fehldefinitionen bzgl. Win16
function GetDlgItemInt(Wnd:HWnd;id:UInt;b:PBool;sign:Bool):UInt; stdcall;
function wvsprintf(s,t:PChar; var v):Integer; stdcall;
function wsprintf0(s,t:PChar):Integer; cdecl;
function wsprintf1(s,t,v1:PChar):Integer; cdecl;
function wsprintf2(s,t,v1,v2:PChar):Integer; cdecl;
function wsprintf3(s,t,v1,v2,v3:PChar):Integer; cdecl;
function wsprintf4(s,t,v1,v2,v3,v4:PChar):Integer; cdecl;
function wsprintf5(s,t,v1,v2,v3,v4,v5:PChar):Integer; cdecl;
function wsprintf6(s,t,v1,v2,v3,v4,v5,v6:PChar):Integer; cdecl;
function wsprintf7(s,t,v1,v2,v3,v4,v5,v6,v7:PChar):Integer; cdecl;
function wsprintf8(s,t,v1,v2,v3,v4,v5,v6,v7,v8:PChar):Integer; cdecl;
function GetWindowUInt(Wnd: HWnd; Index: Integer): UInt; stdcall;
function SetWindowUInt(Wnd: HWnd; Index: Integer; NewWord: UInt): UInt; stdcall;
function GetClassUInt(Wnd: HWnd; Index: Integer): UInt; stdcall;
function SetClassUInt(Wnd: HWnd; Index: Integer; NewWord: UInt): UInt; stdcall;
type
 TS255=array[0..255] of Char;
 TS127=array[0..127] of Char;
 TS63=array[0..63] of Char;
 TS31=array[0..31] of Char;
 TS15=array[0..15] of Char;
 TS7=array[0..7] of Char;
 TS3=array[0..3] of Char;


function min(I1,I2:Integer):Integer;	{Integer=LongInt}
function max(I1,I2:Integer):Integer;

function Bool2MenuCheck(x:Bool):UInt;
function IfThenElse(i:Boolean; t,e:Integer):Integer;	{"?:"-Operator}
function IfThenElseP(i:Boolean; t,e:PChar):PChar;	{"?:"-Operator}
type Bool2MenuGray=UInt;
procedure InitStruct(var s; slen:Integer);
procedure ShortYield;

type
 LongRec=record
  lo,hi:Word;
 end;
 WordRec=record
  lo,hi:Byte;
 end;
 PPChar=^PChar;
type
 TCompProc=function(s1,s2:PChar):Integer; stdcall;

function lstrchr(s:PChar; c:Char):PChar; //stdcall;
{Zeichen <c> im String <Str> suchen, Position liefern}
function lstrcmp1(s_short,s_long:PChar;CP:TCompProc):Integer;
{Anfang von <s_long> mit <s_short> vergleichen, entweder strcmpi oder strcmp}
function lstrstr(needle,heap:PChar;CP:TCompProc):PChar;
{einfache Suche von Nadel in Heuhaufen, entweder strcmpi oder strcmp}

{C-mäßige String-Umwandlung in darstellbares Format}
function EscapeStr(src:PChar; slen:UInt; dst:PChar; dlen:UInt):UInt;
function UnescapeStr(src, dst:PChar; dlen:UInt):UInt;

function GetFileNamePtr(S:PChar):PChar;
{liefert Zeiger hinter das letzte Auftreten von /\: oder Stringanfang}
function GetFileNameExt(S:PChar):PChar;
{liefert Zeiger AUF DEN PUNKT oder AUF DIE NULL, niemals NIL}

function GetRadioCheck(Wnd:HWnd; u,o:UInt):UInt;
function GetCheckboxGroup(Wnd:HWnd; u,o:UInt):UInt;
procedure SetCheckboxGroup(Wnd:HWnd; u,o,x:UInt);
function SendMessageP(Wnd:HWnd;Msg,wParam:UInt;lParam:Pointer):LongInt; stdcall;
function SendDlgItemMsgP(Dlg: HWnd; IDDlgItem: Integer; Msg, wParam: UInt;
  lParam: Pointer): LongInt; stdcall;
function  EnableDlgItem(Wnd:HWnd; idItem:UInt; Enable:Bool):Bool;
{Aktivieren bzw. Grausetzen eines Dialogelements.
 Achtung - Gefahr: Noch keine Fokuskontrolle!}
procedure EnableDlgItemGroup(Wnd:HWnd; u,o:UInt; Enable:Bool);
{Aktivieren bzw. Grausetzen einer Reihe von Dialogfeldern.
 Achtung: Ohne Fokuskontrolle!}
function  ShowDlgItem(Wnd:HWnd; idItem:UInt; iShow:Integer):Bool;
procedure ShowDlgItemGroup(Wnd:HWnd; u,o:UInt; iShow:Integer);
{dito fürs Anzeigen/Verstecken}
procedure SetEditFocus(HWndEdit: HWnd);
{fokussiert+markiert Editfenster}
procedure SortRect(var R:TRect);
	{sortiert die Koordinaten in R so um,
	 daß top/left links oben und bottom/right rechts unten ist}
function MoveRectIntoRect(var R:TRect; const R2:TRect): Bool;
{Dient zum Hineinholen von außerhalb liegenden Fenstern in den Desktop.}
procedure GetFullScreenRect(var R:TRect);
{liefert ideales R2 für MoveRectIntoRect zur Ganz-Anzeige von Dialogen u.ä.}
procedure MoveRectIntoFullScreen(var R:TRect);
{die logische Kombination beider o.g. Routinen}
function iitrafo(x,a,e,ta,te:Integer):Integer;

implementation
function vMBox(WndParent:HWnd; ID,style:Word; var p):Integer;
 var
  S,S2: array[0..255]of Char;	{2 Puffer; leider so erforderlich}
  SPH: PChar;		{Zeiger auf Text und Titel}
  I,K: Integer;
 begin
  I:=LoadString(HInstance,ID,S,sizeof(S)); {I=Anzahl der Zeichen insgesamt}
  K:=lstrlen(S);
  SPH:=StdMBoxTitle;
  if I>K then SPH:=S+K+1;
  wvsprintf(S2,S,P);
  if style and MB_Sound <>0 then MessageBeep(style and $0070);
  vMBox:=MessageBox(WndParent,S2,SPH,style and not MB_Sound);
 end;

function MBox0; external;
function MBox1; external;
function MBox2; external;
function MBox3; external;
function MBox4; external;
function MBox5; external;
function MBox6; external;
function MBox7; external;
function MBox8; external;
{$L mbox32}

//function lstrchr; external 'msvcrt.dll' name 'strchr';
function GetDlgItemInt;		external 'user32.dll' name 'GetDlgItemInt';
function wvsprintf;		external 'user32.dll' name 'wvsprintfA';
function wsprintf0;		external 'user32.dll' name 'wsprintfA';
function wsprintf1;		external 'user32.dll' name 'wsprintfA';
function wsprintf2;		external 'user32.dll' name 'wsprintfA';
function wsprintf3;		external 'user32.dll' name 'wsprintfA';
function wsprintf4;		external 'user32.dll' name 'wsprintfA';
function wsprintf5;		external 'user32.dll' name 'wsprintfA';
function wsprintf6;		external 'user32.dll' name 'wsprintfA';
function wsprintf7;		external 'user32.dll' name 'wsprintfA';
function wsprintf8;		external 'user32.dll' name 'wsprintfA';
function GetWindowUInt;		external 'user32.dll' name 'GetWindowLongA';
function SetWindowUInt;		external 'user32.dll' name 'SetWindowLongA';
function GetClassUInt;		external 'user32.dll' name 'GetClassLongA';
function SetClassUInt;		external 'user32.dll' name 'SetClassLongA';
function SendMessageP;		external 'user32.dll' name 'SendMessageA';
function SendDlgItemMsgP; external 'user32.dll' name 'SendDlgItemMessageA';

function min(I1,I2:Integer):Integer;
 begin if I1<I2 then Result:=I1 else Result:=I2; end;
function max(I1,I2:Integer):Integer;
 begin if I1>I2 then Result:=I1 else Result:=I2; end;
function Bool2MenuCheck(x:Bool):UInt;
 begin if x then Result:=MF_Checked else Result:=MF_UnChecked; end;
function IfThenElse;  begin if i then Result:=t else Result:=e; end;
function IfThenElseP; begin if i then Result:=t else Result:=e; end;

procedure ShortYield;
 var
  Msg: TMsg;
 begin
  if PeekMessage(Msg,0,0,0,PM_Remove) then begin
   TranslateMessage(Msg);
   DispatchMessage(Msg);
  end;
 end;

function IsInvisible(c:Char):Boolean;
{liefert TRUE, wenn Zeichen im üblichen Windows-Zeichensatz nicht sichtbar}
 begin
  IsInvisible:=(c<' ') or (c>=#$80) and (c<#$A0) or (c=#$FF);
 end;

function EscapeStr(src:PChar; slen:UInt; dst:PChar; dlen:UInt):UInt;
{Wandelt übergebene "Bytefolge" (nicht nullterminiert) in C-String
 mit Escape-Sequenzen um, auch \" und \' und \\. Nicht darstellbare
 Zeichen werden in \a, \b usw. und ansonsten in Hex (\xXX) umgesetzt.
 Liefert als Ergebnis die Länge des Ergebnisstrings ohne \0.
 src und dst dürfen sich nicht überlappen.}
 var
  su:record
   case Integer of
    1: (c: Char);
    2: (i: Integer);	{Ausrichtungs-Problem bei wvsprintf}
  end;
  ChrCount: UInt;	{geht hier nicht mit "Result"!}
 function fcat(template:PChar; len:UInt):Boolean;
  begin
   fcat:=false;
   if len<dlen then begin
    if template<>nil
    then wvsprintf(dst,template,su.i)
    else dst^:=su.c;
    Inc(dst,len);
    Inc(ChrCount,len);
    Dec(dlen,len);
    fcat:=true;
   end;
  end;
 begin
  ChrCount:=0;
  while slen>0 do begin
   su.i:=0;
   case src^ of
    '\','"','''': su.c:=src^;
    #7:  su.c:='a';
    #8:  su.c:='b';
    #9:  su.c:='t';
    #10: su.c:='n';
    #11: su.c:='v';
    #13: su.c:='r';
   end;
   if su.i<>0 then begin
    if not fcat('\%c',2) then break;
   end else begin
    su.c:=src^;
    if IsInvisible(su.c) then begin
     if not fcat('\x%02X',4) then break;
    end else begin
     if not fcat(nil,1) then break;
    end;
   end;
   Inc(src);
   Dec(slen);
  end{while};
  if dlen>0 then dst^:=#0;	{terminieren}
  EscapeStr:=ChrCount;
 end;

function UnescapeStr(src, dst:PChar; dlen:UInt):UInt;
{Wandelt übergebenen C-String (nullterminiert) in "Bytefolge".
 Liefert als Ergebnis die Länge der Ergebnis-Bytefolge -
 diese ist nicht nullterminiert!
 Da der Ergebnisstring niemals länger wird, darf src=dst sein.}
 var
  su,st: Char;
  e,f: Integer;
 begin
  Result:=0;
  while dlen>0 do begin
   su:=src^;
   Inc(src);
   if su=#0 then break;
   if su='\' then begin
    su:=src^;
    Inc(src);
    case su of
     #0: break;
     '0': su:=#0;	{Hier: Keine Oktalzahlen - nur dieser Sonderfall}
     '1'..'9': begin
      Dec(src);
      Val(src,Byte(su),e);	{liefert als Fehler Zeichenpos+1!}
      if e<>0 then begin
       Dec(e);
       st:=src[e];
       src[e]:=#0;
       Val(src,Byte(su),f);	{sollte f=0 liefern, ist jedoch belanglos}
       Inc(src,e);
       src^:=st;		{Zurückpatchen}
      end else Inc(src,lstrlen(src));	{falls gerade am Stringende}
     end;
     'a': su:=#7;
     'b': su:=#8;
     't': su:=#9;
     'n': su:=#10;
     'v': su:=#11;
     'r': su:=#13;
     'x': begin
      st:=src[2];
      src[2]:=#0;
      Dec(src);
      src[0]:='$';
      Val(src,Byte(su),e);
      src[0]:='x';		{Zurückpatchen}
      Inc(src);
      src[2]:=st;		{Zurückpatchen}
      if e=0 then Inc(src,2) else su:='x';
     end;
    end{case};		{im ELSE-Fall bleibt "su" literal!}
   end{if};
   dst^:=su;
   Inc(dst);
   Inc(Result);
   Dec(dlen);
  end;
 end;

function GetFileNamePtr(S:PChar):PChar;
{liefert Zeiger hinter das letzte Auftreten von /\: oder Stringanfang}
 begin
  Result:=S;
  repeat
   case S^ of
    #0: exit;
    ':','\','/': Result:=S+1;
   end;
   S:=AnsiNext(S);
  until false;
 end;

function GetFileNameExt(S:PChar):PChar;
{liefert Zeiger AUF DEN PUNKT oder AUF DIE TERMINIERENDE NULL, niemals NIL}
{Als Extension gilt hierbei die Zeichenkette beginnend am _letzten_
 Punkt in der _letzten_ Pfadkomponente, wenn dieser Punkt nicht
 am Anfang steht (wie bei den versteckten Dateien unter UNIX)
 und auch nicht als Folge von Punkten am Anfang steht (wie bei ..)
*Voraussetzung für das korrekte Funktionieren dieser Funktion ist,
 daß der Dateiname keinen anhängigen Pfad-Trenner (/\:) hat.}
 begin
  S:=GetFileNamePtr(S);
  while S^='.' do Inc(S);
  Result:=nil;
  repeat
   case S^ of
    #0: begin if Result=nil then Result:=S; exit; end;
    '.': Result:=S;
   end;
   Inc(S);
  until false;
 end;

function GetRadioCheck(Wnd:HWnd; u,o:UInt):UInt;
 begin
  Result:=0;
  while u<=o do begin
   if IsDlgButtonChecked(Wnd,u)=1 then exit;
   Inc(u);
   Inc(Result);
  end;
 end;

function GetCheckboxGroup(Wnd:HWnd; u,o:UInt):UInt;
 var
  Mask:UInt;
 begin
  Result:=0;
  Mask:=1;
  while u<=o do begin
   if IsDlgButtonChecked(Wnd,u)=1 then Result:=Result or Mask;
   Inc(u);
   Mask:=Mask shl 1;
  end;
 end;
 
procedure SetCheckboxGroup(Wnd:HWnd; u,o,x:UInt);
 begin
  while u<=o do begin
   CheckDlgButton(Wnd,u,x and 1);
   Inc(u);
   x:=x shr 1;
  end;
 end;

procedure SetCheckboxGroup2(Wnd:HWnd; u,o,x:UInt);
{wie oben, belΣ▀t jedoch Felder im dritten Zustand unverΣndert}
 begin
  while u<=o do begin
   if IsDlgButtonChecked(Wnd,u)<2
   then CheckDlgButton(Wnd,u,x and 1);
   Inc(u);
   x:=x shr 1;
  end;
 end;

function EnableDlgItem(Wnd:HWnd; idItem:UInt; Enable:Bool):Bool;
 begin
  HWnd(result):=GetDlgItem(Wnd,idItem);
  if result then result:=EnableWindow(HWnd(result),Enable);
 end;

procedure EnableDlgItemGroup(Wnd:HWnd; u,o:UInt; Enable:Bool);
 begin
  Dec(u);
  repeat
   Inc(u);
   EnableDlgItem(Wnd,u,Enable);
  until u=o;
 end;

function  ShowDlgItem(Wnd:HWnd; idItem:UInt; iShow:Integer):Bool;
 begin
  HWnd(result):=GetDlgItem(Wnd,idItem);
  if result then result:=ShowWindow(HWnd(result),iShow);
 end;

procedure ShowDlgItemGroup(Wnd:HWnd; u,o:UInt; iShow:Integer);
 begin
  Dec(u);
  repeat
   Inc(u);
   ShowDlgItem(Wnd,u,iShow);
  until u=o;
 end;

procedure SetEditFocus(HWndEdit: HWnd);
{fokussiert+markiert Editfenster}
 begin
  SetFocus(HWndEdit);
  SendMessage(HWndEdit,EM_SetSel,0,-1);
 end;
 
procedure SortRect(var R:TRect);
{sortiert die Punkte, da▀ die Zuordnungen stimmen}
 var t: Integer;
 begin
  with R do begin
   if left>right then begin t:=left; left:=right; right:=t; end;
   if top>bottom then begin t:=top; top:=bottom; bottom:=t; end;
  end;
 end;

function ShiftRect(r,r2: PInteger):Bool;
{Kommentar siehe www.tu-chemnitz.de/~heha/messtech/sensokom.zip/dialog.c}
 var ax,dx:Integer;
 begin
  Result:=false;
  ax:=r2^-r^;
  if ax=0 then exit;
  if ax<0 then begin
   Inc(r,2); Inc(r2,2);
   dx:=r2^-r^;
   if dx>=0 then exit;
   if ax<dx then ax:=dx;
   Dec(r,2); Dec(r2,2);
  end;
  Inc(r^,ax);
  Inc(r,2);
  Inc(r^,ax);
  Result:=true;
 end;

function MoveRectIntoRect(var R:TRect; const R2:TRect): Bool;
{Falls R in R2 teilweise oder vollstΣndig au▀erhalb liegt,
 wird R verschoben und TRUE zurⁿckgeliefert, um maximale Sichtbarkeit
 zu realisieren.
 Dient zum Hineinholen von au▀erhalb liegenden Fenstern in den Desktop.}
 begin
  Result:=Bool(Integer(ShiftRect(@R.left,@R2.left))
    +Integer(ShiftRect(@R.top,@R2.top)));
 end;

procedure GetFullScreenRect(var R:TRect);
{Ermittelt das Rechteck fⁿr maximierte Fenster, d.h. die Startleiste(n)
 von Win9x bereits abgezogen, ideal fⁿr R2 in MoveRectIntoRect}
 begin
  with R do begin
   left:=0;
   top:=0;
   right:=GetSystemMetrics(SM_CXFullScreen);
   bottom:=GetSystemMetrics(SM_CYFullScreen)+GetSystemMetrics(SM_CYCaption);
  end;
 end;

procedure MoveRectIntoFullScreen(var R:TRect);
{die logische Kombination beider o.g. Routinen}
 var
  R2: TRect;
 begin
  GetFullScreenRect(R2);
  MoveRectIntoRect(R,R2);
 end;

function iitrafo(x,a,e,ta,te:Integer):Integer;
 begin
  Result:=IfThenElse(e<>a,MulDiv(x-a,te-ta,e-a)+ta,0);
 end;

function lstrchr(s:PChar; c:Char):PChar;
 begin
  repeat
   if s^=c then begin Result:=s; exit; end;
   if s^=#0 then break;
   s:=AnsiNext(s);
  until false;
  Result:=nil;
 end;

function lstrcmp1(s_short,s_long:PChar;CP:TCompProc):Integer;
 var
  rp: PChar;
  cm: Char;
 begin
  rp:=s_long+lstrlen(s_short);
  cm:=rp^;
  rp^:=#0;			{patchen}
  Result:=CP(s_short,s_long);
  rp^:=cm;			{zurückpatchen}
 end;

function lstrstr(needle,heap:PChar; CP:TCompProc):PChar;
 var
  ln,lh,cc,cr:Integer;
  cm: Char;
  h_end,rp: PChar;
 begin
  ln:=lstrlen(needle);
  lh:=lstrlen(heap);
  cc:=lh-ln;
  if cc<0 then begin Result:=nil; exit; end;
			{Nadel länger als Heu: kann nicht sein!}
  h_end:=heap+cc;
  while heap<=h_end do begin
   rp:=heap+ln;
   cm:=rp^;
   rp^:=#0;		{Patch!}
   cr:=CP(heap,needle);
   rp^:=cm;		{Rückpatch!}
   if cr=0 then begin Result:=heap; exit; end;
   heap:=AnsiNext(heap);
  end;
  Result:=nil;
 end;

procedure InitStruct(var s; slen:Integer);
 begin
  ZeroMemory(@s,slen);
  PInteger(@s)^:=slen;
 end;
end.
(*
function min(I1,I2:Integer):Integer;	{Integer=LongInt}
 inline($58/$59/$39/$C8/$7C/$01/$91);
	{pop eax; pop ecx; cmp eax,ecx; jl $+3; xchg ecx,eax}
function max(I1,I2:Integer):Integer;
 inline($58/$59/$39/$C8/$7F/$01/$91);
	{pop eax; pop ecx; cmp eax,ecx; jg $+3; xchg ecx,eax}
*)
Detected encoding: OEM (CP437)1
Wrong umlauts? - Assume file is ANSI (CP1252) encoded