| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283 | {    This file is part of the Free Pascal Integrated Development Environment    Copyright (c) 1998 by Berczi Gabor    See the file COPYING.FPC, included in this distribution,    for details about the copyright.    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. **********************************************************************}unit WUtils;interfaceuses{$ifdef Windows}  windows,{$endif Windows}{$ifdef netwlibc}  libc,{$else}  {$ifdef netware}    nwserv,  {$endif}{$endif}{$ifdef Unix}  baseunix,  unix,{$endif Unix}  Dos,Objects;const      kbCtrlGrayPlus         = $9000;      kbCtrlGrayMinus        = $8e00;      kbCtrlGrayMul          = $9600;  TempFirstChar = {$ifndef Unix}'~'{$else}'_'{$endif};  TempExt       = '.tmp';  TempNameLen   = 8;  EOL : String[2] = {$ifdef Unix}#10;{$else}#13#10;{$endif}type  PByteArray = ^TByteArray;  TByteArray = array[0..MaxBytes] of byte;  PNoDisposeCollection = ^TNoDisposeCollection;  TNoDisposeCollection = object(TCollection)    procedure FreeItem(Item: Pointer); virtual;  end;  PUnsortedStringCollection = ^TUnsortedStringCollection;  TUnsortedStringCollection = object(TCollection)    constructor CreateFrom(ALines: PUnsortedStringCollection);    procedure   Assign(ALines: PUnsortedStringCollection);    function    At(Index: Sw_Integer): PString;    procedure   FreeItem(Item: Pointer); virtual;    function    GetItem(var S: TStream): Pointer; virtual;    procedure   PutItem(var S: TStream; Item: Pointer); virtual;    procedure   InsertStr(const S: string);  end;  PNulStream = ^TNulStream;  TNulStream = object(TStream)    constructor Init;    function    GetPos: Longint; virtual;    function    GetSize: Longint; virtual;    procedure   Read(var Buf; Count: longint); virtual;    procedure   Seek(Pos: Longint); virtual;    procedure   Write(var Buf; Count: longint); virtual;  end;  PSubStream = ^TSubStream;  TSubStream = object(TStream)    constructor Init(AStream: PStream; AStartPos, ASize: longint);    function    GetPos: Longint; virtual;    function    GetSize: Longint; virtual;    procedure   Read(var Buf; Count: longint); virtual;    procedure   Seek(Pos: Longint); virtual;    procedure   Write(var Buf; Count: longint); virtual;  private    StartPos: longint;    S       : PStream;  end;  PFastBufStream = ^TFastBufStream;  TFastBufStream = object(TBufStream)    constructor Init (FileName: FNameStr; Mode, Size: Word);    procedure   Seek(Pos: Longint); virtual;    procedure Readline(var s:string;var linecomplete,hasCR : boolean);  private    BasePos: longint;  end;  PTextCollection = ^TTextCollection;  TTextCollection = object(TStringCollection)    function LookUp(const S: string; var Idx: sw_integer): string;    function Compare(Key1, Key2: Pointer): sw_Integer; virtual;  end;  PIntCollection = ^TIntCollection;  TIntCollection = object(TSortedCollection)    function  Compare(Key1, Key2: Pointer): sw_Integer; virtual;    procedure FreeItem(Item: Pointer); virtual;    procedure Add(Item: ptrint);    function  Contains(Item: ptrint): boolean;    function  AtInt(Index: sw_integer): ptrint;  end;procedure ReadlnFromStream(Stream: PStream; var s:string;var linecomplete,hasCR : boolean);function eofstream(s: pstream): boolean;procedure ReadlnFromFile(var f : file; var S:string;           var linecomplete,hasCR : boolean;           BreakOnSpacesOnly : boolean);function Min(A,B: longint): longint;function Max(A,B: longint): longint;function CharStr(C: char; Count: integer): string;function UpcaseStr(const S: string): string;function LowCase(C: char): char;function LowcaseStr(S: string): string;function RExpand(const S: string; MinLen: byte): string;function LExpand(const S: string; MinLen: byte): string;function LTrim(const S: string): string;function RTrim(const S: string): string;function Trim(const S: string): string;function IntToStr(L: longint): string;function IntToStrL(L: longint; MinLen: sw_integer): string;function IntToStrZ(L: longint; MinLen: sw_integer): string;function StrToInt(const S: string): longint;function StrToCard(const S: string): cardinal;function FloatToStr(D: Double; Decimals: byte): string;function FloatToStrL(D: Double; Decimals: byte; MinLen: byte): string;function GetStr(P: PString): string;function GetPChar(P: PChar): string;function BoolToStr(B: boolean; const TrueS, FalseS: string): string;function LExtendString(S: string; MinLen: byte): string;function DirOf(const S: string): string;function ExtOf(const S: string): string;function NameOf(const S: string): string;function NameAndExtOf(const S: string): string;function DirAndNameOf(const S: string): string;{ return Dos GetFTime value or -1 if the file does not exist }function GetFileTime(const FileName: string): longint;{ copied from compiler global unit }function GetShortName(const n:string):string;function GetLongName(const n:string):string;function TrimEndSlash(const Path: string): string;function CompleteDir(const Path: string): string;function GetCurDir: string;function OptimizePath(Path: string; MaxLen: integer): string;function CompareText(S1, S2: string): integer;function ExistsDir(const DirName: string): boolean;function ExistsFile(const FileName: string): boolean;function SizeOfFile(const FileName: string): longint;function DeleteFile(const FileName: string): integer;function CopyFile(const SrcFileName, DestFileName: string): boolean;function GenTempFileName: string;function FormatPath(Path: string): string;function CompletePath(const Base, InComplete: string): string;function CompleteURL(const Base, URLRef: string): string;function EatIO: integer;function Now: longint;function FormatDateTimeL(L: longint; const Format: string): string;function FormatDateTime(const D: DateTime; const Format: string): string;function MemToStr(var B; Count: byte): string;procedure StrToMem(S: string; var B);const LastStrToIntResult : integer = 0;      LastHexToIntResult : integer = 0;      LastStrToCardResult : integer = 0;      LastHexToCardResult : integer = 0;      DirSep             : char    = {$ifdef Unix}'/'{$else}'\'{$endif};      UseOldBufStreamMethod : boolean = false;procedure RegisterWUtils;Procedure DebugMessage(AFileName, AText : string; ALine, APos : sw_word); // calls DebugMessageProcedure WUtilsDebugMessage(AFileName, AText : string; ALine, APos : string; nrLine, nrPos : sw_word);type  TDebugMessage = procedure(AFileName, AText : string; ALine, APos : String; nrLine, nrPos : sw_word);Const  DebugMessageS : TDebugMessage = @WUtilsDebugMessage;implementationuses{$IFDEF OS2}  DosCalls,{$ENDIF OS2}  Strings;{$ifndef NOOBJREG}const   SpaceStr = '                                                            '+              '                                                            '+              '                                                            '+              '                                                            ' ;  RUnsortedStringCollection: TStreamRec = (     ObjType: 22500;     VmtLink: Ofs(TypeOf(TUnsortedStringCollection)^);     Load:    @TUnsortedStringCollection.Load;     Store:   @TUnsortedStringCollection.Store  );{$endif}function eofstream(s: pstream): boolean;begin  eofstream:=(s^.getpos>=s^.getsize);end;procedure ReadlnFromStream(Stream: PStream; var S:string;var linecomplete,hasCR : boolean);  var    c : char;    i,pos : longint;  begin    linecomplete:=false;    c:=#0;    i:=0;    { this created problems for lines longer than 255 characters      now those lines are cutted into pieces without warning PM }    { changed implicit 255 to High(S), so it will be automatically extended      when longstrings eventually become default - Gabor }    while (not eofstream(stream)) and (c<>#10) and (i<High(S)) do     begin       stream^.read(c,sizeof(c));       if c<>#10 then        begin          inc(i);          s[i]:=c;        end;     end;    { if there was a CR LF then remove the CR Dos newline style }    if (i>0) and (s[i]=#13) then      begin        dec(i);      end;    if (c=#13) and (not eofstream(stream)) then      stream^.read(c,sizeof(c));    if (i=High(S)) and not eofstream(stream) then      begin        pos:=stream^.getpos;        stream^.read(c,sizeof(c));        if (c=#13) and not eofstream(stream) then          stream^.read(c,sizeof(c));        if c<>#10 then          stream^.seek(pos);      end;    if (c=#10) or eofstream(stream) then      linecomplete:=true;    if (c=#10) then      hasCR:=true;    s[0]:=chr(i);  end;procedure ReadlnFromFile(var f : file; var S:string;           var linecomplete,hasCR : boolean;           BreakOnSpacesOnly : boolean);  var    c : char;    i,pos,    lastspacepos,LastSpaceFilePos : longint;{$ifdef DEBUG}    filename: string;{$endif DEBUG}  begin    LastSpacePos:=0;    linecomplete:=false;    c:=#0;    i:=0;    { this created problems for lines longer than 255 characters      now those lines are cutted into pieces without warning PM }    { changed implicit 255 to High(S), so it will be automatically extended      when longstrings eventually become default - Gabor }    while (not eof(f)) and (c<>#10) and (i<High(S)) do     begin       system.blockread(f,c,sizeof(c));       if c<>#10 then        begin          inc(i);          s[i]:=c;        end;       if BreakOnSpacesOnly and (c=' ') then         begin           LastSpacePos:=i;           LastSpaceFilePos:=system.filepos(f);         end;     end;    { if there was a CR LF then remove the CR Dos newline style }    if (i>0) and (s[i]=#13) then      begin        dec(i);      end;    if (c=#13) and (not eof(f)) then      system.blockread(f,c,sizeof(c));    if (i=High(S)) and not eof(f) then      begin        pos:=system.filepos(f);        system.blockread(f,c,sizeof(c));        if (c=#13) and not eof(f) then          system.blockread(f,c,sizeof(c));        if c<>#10 then          system.seek(f,pos);        if (c<>' ') and (c<>#10) and BreakOnSpacesOnly and           (LastSpacePos>1) then          begin{$ifdef DEBUG}            s[0]:=chr(i);            filename:=strpas(@(filerec(f).Name));            DebugMessage(filename,'s='+s,1,1);{$endif DEBUG}            i:=LastSpacePos;{$ifdef DEBUG}            s[0]:=chr(i);            DebugMessage(filename,'reduced to '+s,1,1);{$endif DEBUG}            system.seek(f,LastSpaceFilePos);          end;      end;    if (c=#10) or eof(f) then      linecomplete:=true;    if (c=#10) then      hasCR:=true;    s[0]:=chr(i);  end;function MemToStr(var B; Count: byte): string;var S: string;begin  S[0]:=chr(Count);  if Count>0 then Move(B,S[1],Count);  MemToStr:=S;end;procedure StrToMem(S: string; var B);begin  if length(S)>0 then Move(S[1],B,length(S));end;function Max(A,B: longint): longint;begin  if A>B then Max:=A else Max:=B;end;function Min(A,B: longint): longint;begin  if A<B then Min:=A else Min:=B;end;function CharStr(C: char; Count: integer): string;begin  if Count<=0 then    begin      CharStr:='';      exit;    end  else if Count>255 then    Count:=255;  CharStr[0]:=chr(Count);  FillChar(CharStr[1],Count,C);end;function UpcaseStr(const S: string): string;var  I: Longint;begin  for I:=1 to length(S) do    if S[I] in ['a'..'z'] then      UpCaseStr[I]:=chr(ord(S[I])-32)    else      UpCaseStr[I]:=S[I];  UpcaseStr[0]:=S[0];end;function RExpand(const S: string; MinLen: byte): string;begin  if length(S)<MinLen then    RExpand:=S+CharStr(' ',MinLen-length(S))  else    RExpand:=S;end;function LExpand(const S: string; MinLen: byte): string;begin  if length(S)<MinLen then    LExpand:=CharStr(' ',MinLen-length(S))+S  else    LExpand:=S;end;function LTrim(const S: string): string;var  i : longint;begin  i:=1;  while (i<length(s)) and (s[i]=' ') do   inc(i);  LTrim:=Copy(s,i,High(S));end;function RTrim(const S: string): string;var  i : longint;begin  i:=length(s);  while (i>0) and (s[i]=' ') do   dec(i);  RTrim:=Copy(s,1,i);end;function Trim(const S: string): string;var  i,j : longint;begin  i:=1;  while (i<length(s)) and (s[i]=' ') do   inc(i);  j:=length(s);  while (j>0) and (s[j]=' ') do   dec(j);  Trim:=Copy(S,i,j-i+1);end;function IntToStr(L: longint): string;var S: string;begin  Str(L,S);  IntToStr:=S;end;function IntToStrL(L: longint; MinLen: sw_integer): string;begin  IntToStrL:=LExpand(IntToStr(L),MinLen);end;function IntToStrZ(L: longint; MinLen: sw_integer): string;var S: string;begin  S:=IntToStr(L);  if length(S)<MinLen then    S:=CharStr('0',MinLen-length(S))+S;  IntToStrZ:=S;end;function StrToInt(const S: string): longint;var L: longint;    C: integer;begin  Val(S,L,C); if C<>0 then L:=-1;  LastStrToIntResult:=C;  StrToInt:=L;end;function StrToCard(const S: string): cardinal;var L: cardinal;    C: integer;begin  Val(S,L,C); if C<>0 then L:=$ffffffff;  LastStrToCardResult:=C;  StrToCard:=L;end;function FloatToStr(D: Double; Decimals: byte): string;var S: string;    L: byte;begin  Str(D:0:Decimals,S);  if length(S)>0 then  while (S[1]=' ') do Delete(S,1,1);  FloatToStr:=S;end;function FloatToStrL(D: Double; Decimals: byte; MinLen: byte): string;begin  FloatToStrL:=LExtendString(FloatToStr(D,Decimals),MinLen);end;function LExtendString(S: string; MinLen: byte): string;begin  LExtendString:=copy(SpaceStr,1,MinLen-length(S))+S;end;function GetStr(P: PString): string;begin  if P=nil then GetStr:='' else GetStr:=P^;end;function GetPChar(P: PChar): string;begin  if P=nil then GetPChar:='' else GetPChar:=StrPas(P);end;function DirOf(const S: string): string;var D: DirStr; E: ExtStr; N: NameStr;begin  FSplit(S,D,N,E);  if (D<>'') and (D[Length(D)]<>DirSep) then   DirOf:=D+DirSep  else   DirOf:=D;end;function ExtOf(const S: string): string;var D: DirStr; E: ExtStr; N: NameStr;begin  FSplit(S,D,N,E);  ExtOf:=E;end;function NameOf(const S: string): string;var D: DirStr; E: ExtStr; N: NameStr;begin  FSplit(S,D,N,E);  NameOf:=N;end;function NameAndExtOf(const S: string): string;var D: DirStr; E: ExtStr; N: NameStr;begin  FSplit(S,D,N,E);  NameAndExtOf:=N+E;end;function DirAndNameOf(const S: string): string;var D: DirStr; E: ExtStr; N: NameStr;begin  FSplit(S,D,N,E);  DirAndNameOf:=D+N;end;{ return Dos GetFTime value or -1 if the file does not exist }function GetFileTime(const FileName: string): longint;var T: longint;    f: file;    FM: integer;begin  if FileName='' then    T:=-1  else    begin      FM:=FileMode; FileMode:=0;      EatIO; Dos.DosError:=0;      Assign(f,FileName);      {$I-}      Reset(f);      if InOutRes=0 then        begin          GetFTime(f,T);          Close(f);        end;      {$I+}      if (EatIO<>0) or (Dos.DosError<>0) then T:=-1;      FileMode:=FM;    end;  GetFileTime:=T;end;function GetShortName(const n:string):string;{$ifdef Windows}var  hs,hs2 : string;  i : longint;{$endif}{$ifdef go32v2}var  hs : string;{$endif}begin  GetShortName:=n;{$ifdef Windows}  hs:=n+#0;  i:=Windows.GetShortPathName(@hs[1],@hs2[1],high(hs2));  if (i>0) and (i<=high(hs2)) then    begin      hs2[0]:=chr(strlen(@hs2[1]));      GetShortName:=hs2;    end;{$endif}{$ifdef go32v2}  hs:=n;  if Dos.GetShortName(hs) then   GetShortName:=hs;{$endif}end;function GetLongName(const n:string):string;{$ifdef Windows}var  hs : string;  hs2 : Array [0..255] of char;  i : longint;  j : pchar;{$endif}{$ifdef go32v2}var  hs : string;{$endif}begin  GetLongName:=n;{$ifdef Windows}  hs:=n+#0;  i:=Windows.GetFullPathName(@hs[1],256,hs2,j);  if (i>0) and (i<=high(hs)) then    begin      hs:=strpas(hs2);      GetLongName:=hs;    end;{$endif}{$ifdef go32v2}  hs:=n;  if Dos.GetLongName(hs) then   GetLongName:=hs;{$endif}end;function EatIO: integer;begin  EatIO:=IOResult;end;function LowCase(C: char): char;begin  if ('A'<=C) and (C<='Z') then C:=chr(ord(C)+32);  LowCase:=C;end;function LowcaseStr(S: string): string;var I: Longint;begin  for I:=1 to length(S) do      S[I]:=Lowcase(S[I]);  LowcaseStr:=S;end;function BoolToStr(B: boolean; const TrueS, FalseS: string): string;begin  if B then BoolToStr:=TrueS else BoolToStr:=FalseS;end;procedure TNoDisposeCollection.FreeItem(Item: Pointer);begin  { don't do anything here }end;constructor TUnsortedStringCollection.CreateFrom(ALines: PUnsortedStringCollection);begin  if Assigned(ALines)=false then Fail;  inherited Init(ALines^.Count,ALines^.Count div 10);  Assign(ALines);end;procedure TUnsortedStringCollection.Assign(ALines: PUnsortedStringCollection);procedure AddIt(P: PString);begin  Insert(NewStr(GetStr(P)));end;begin  FreeAll;  if Assigned(ALines) then    ALines^.ForEach(@AddIt);end;procedure TUnsortedStringCollection.InsertStr(const S: string);begin  Insert(NewStr(S));end;function TUnsortedStringCollection.At(Index: Sw_Integer): PString;begin  At:=inherited At(Index);end;procedure TUnsortedStringCollection.FreeItem(Item: Pointer);begin  if Item<>nil then DisposeStr(Item);end;function TUnsortedStringCollection.GetItem(var S: TStream): Pointer;begin  GetItem:=S.ReadStr;end;procedure TUnsortedStringCollection.PutItem(var S: TStream; Item: Pointer);begin  S.WriteStr(Item);end;function TIntCollection.Contains(Item: ptrint): boolean;var Index: sw_integer;begin  Contains:=Search(pointer(Item),Index);end;function TIntCollection.AtInt(Index: sw_integer): ptrint;begin  AtInt:=longint(At(Index));end;procedure TIntCollection.Add(Item: ptrint);begin  Insert(pointer(Item));end;function TIntCollection.Compare(Key1, Key2: Pointer): sw_Integer;var K1: longint absolute Key1;    K2: longint absolute Key2;    R: integer;begin  if K1<K2 then R:=-1 else  if K1>K2 then R:= 1 else  R:=0;  Compare:=R;end;procedure TIntCollection.FreeItem(Item: Pointer);begin  { do nothing here }end;constructor TNulStream.Init;begin  inherited Init;  Position:=0;end;function TNulStream.GetPos: Longint;begin  GetPos:=Position;end;function TNulStream.GetSize: Longint;begin  GetSize:=Position;end;procedure TNulStream.Read(var Buf; Count: longint);begin  Error(stReadError,0);end;procedure TNulStream.Seek(Pos: Longint);begin  if Pos<=Position then    Position:=Pos;end;procedure TNulStream.Write(var Buf; Count: longint);begin  Inc(Position,Count);end;constructor TSubStream.Init(AStream: PStream; AStartPos, ASize: longint);begin  inherited Init;  if Assigned(AStream)=false then Fail;  S:=AStream; StartPos:=AStartPos; StreamSize:=ASize;  Seek(0);end;function TSubStream.GetPos: Longint;var Pos: longint;begin  Pos:=S^.GetPos; Dec(Pos,StartPos);  GetPos:=Pos;end;function TSubStream.GetSize: Longint;begin  GetSize:=StreamSize;end;procedure TSubStream.Read(var Buf; Count: longint);var Pos: longint;    RCount: longint;begin  Pos:=GetPos;  if Pos+Count>StreamSize then RCount:=StreamSize-Pos else RCount:=Count;  S^.Read(Buf,RCount);  if RCount<Count then    Error(stReadError,0);end;procedure TSubStream.Seek(Pos: Longint);var RPos: longint;begin  if (Pos<=StreamSize) then RPos:=Pos else RPos:=StreamSize;  S^.Seek(StartPos+RPos);end;procedure TSubStream.Write(var Buf; Count: longint);begin  S^.Write(Buf,Count);end;constructor TFastBufStream.Init (FileName: FNameStr; Mode, Size: Word);begin  Inherited Init(FileName,Mode,Size);  BasePos:=0;end;procedure TFastBufStream.Seek(Pos: Longint);var RelOfs: longint;begin  RelOfs:=Pos-BasePos;  if (RelOfs<0) or (RelOfs>=BufEnd) or (BufEnd=0) then    begin      inherited Seek(Pos);      BasePos:=Pos-BufPtr;    end  else    begin      BufPtr:=RelOfs;      Position:=Pos;    end;end;procedure TFastBufStream.Readline(var s:string;var linecomplete,hasCR : boolean);  var    c : char;    i,pos,StartPos : longint;    charsInS : boolean;  begin    linecomplete:=false;    c:=#0;    i:=0;    { this created problems for lines longer than 255 characters      now those lines are cutted into pieces without warning PM }    { changed implicit 255 to High(S), so it will be automatically extended      when longstrings eventually become default - Gabor }    if (bufend-bufptr>=High(S)) and (getpos+High(S)<getsize) then      begin        StartPos:=GetPos;        //read(S[1],High(S));        system.move(buffer^[bufptr],S[1],High(S));        charsInS:=true;      end    else      CharsInS:=false;    while (CharsInS or not (getpos>=getsize)) and          (c<>#10) and (i<High(S)) do     begin       if CharsInS then         c:=s[i+1]       else         read(c,sizeof(c));       if c<>#10 then        begin          inc(i);          if not CharsInS then            s[i]:=c;        end;     end;    if CharsInS then      begin        if c=#10 then          Seek(StartPos+i+1)        else          Seek(StartPos+i);      end;    { if there was a CR LF then remove the CR Dos newline style }    if (i>0) and (s[i]=#13) then      begin        dec(i);      end;    if (c=#13) and (not (getpos>=getsize)) then      begin        read(c,sizeof(c));      end;    if (i=High(S)) and not (getpos>=getsize) then      begin        pos:=getpos;        read(c,sizeof(c));        if (c=#13) and not (getpos>=getsize) then          read(c,sizeof(c));        if c<>#10 then          seek(pos);      end;    if (c=#10) or (getpos>=getsize) then      linecomplete:=true;    if (c=#10) then      hasCR:=true;    s[0]:=chr(i);  end;function TTextCollection.Compare(Key1, Key2: Pointer): Sw_Integer;var K1: PString absolute Key1;    K2: PString absolute Key2;    R: Sw_integer;    S1,S2: string;begin  S1:=UpCaseStr(K1^);  S2:=UpCaseStr(K2^);  if S1<S2 then R:=-1 else  if S1>S2 then R:=1 else  R:=0;  Compare:=R;end;function TTextCollection.LookUp(const S: string; var Idx: sw_integer): string;var OLI,ORI,Left,Right,Mid: integer;    {LeftP,RightP,}MidP: PString;    {LeftS,}MidS{,RightS}: string;    FoundS: string;    UpS : string;begin  Idx:=-1; FoundS:='';  Left:=0; Right:=Count-1;  UpS:=UpCaseStr(S);  while Left<=Right do    begin      OLI:=Left; ORI:=Right;      Mid:=Left+(Right-Left) div 2;      MidP:=At(Mid);      MidS:=UpCaseStr(MidP^);      if copy(MidS,1,length(UpS))=UpS then        begin          Idx:=Mid; FoundS:=GetStr(MidP);          { exit immediately if exact match PM }          If Length(MidS)=Length(UpS) then            break;        end;      if UpS<MidS then        Right:=Mid      else        Left:=Mid;      if (OLI=Left) and (ORI=Right) then        begin          if (Left<Right) then            Left:=Right          else            Break;        end;    end;  LookUp:=FoundS;end;function TrimEndSlash(const Path: string): string;var S: string;begin  S:=Path;  if (length(S)>0) and (S<>DirSep) and (copy(S,length(S),1)=DirSep) and    (S[length(S)-1]<>':') then   S:=copy(S,1,length(S)-1);  TrimEndSlash:=S;end;function CompareText(S1, S2: string): integer;var R: integer;begin  S1:=UpcaseStr(S1); S2:=UpcaseStr(S2);  if S1<S2 then R:=-1 else  if S1>S2 then R:= 1 else  R:=0;  CompareText:=R;end;function FormatPath(Path: string): string;var P: sw_integer;    SC: char;begin  if ord(DirSep)=ord('/') then    SC:='\'  else    SC:='/';  repeat    P:=Pos(SC,Path);    if P>0 then Path[P]:=DirSep;  until P=0;  FormatPath:=Path;end;function CompletePath(const Base, InComplete: string): string;var Drv,BDrv: string[40]; D,BD: DirStr; N,BN: NameStr; E,BE: ExtStr;    P: sw_integer;    Complete: string;begin  Complete:=FormatPath(InComplete);  FSplit(FormatPath(InComplete),D,N,E);  P:=Pos(':',D); if P=0 then Drv:='' else begin Drv:=copy(D,1,P); Delete(D,1,P); end;  FSplit(FormatPath(Base),BD,BN,BE);  P:=Pos(':',BD); if P=0 then BDrv:='' else begin BDrv:=copy(BD,1,P); Delete(BD,1,P); end;  if copy(D,1,1)<>DirSep then    Complete:=BD+D+N+E;  if Drv='' then    Complete:=BDrv+Complete;  Complete:=FExpand(Complete);  CompletePath:=Complete;end;function CompleteURL(const Base, URLRef: string): string;var P: integer;    Drive: string[20];    IsComplete: boolean;    S: string;    Ref: string;    Bookmark: string;begin  IsComplete:=false; Ref:=URLRef;  P:=Pos(':',Ref);  if P=0 then Drive:='' else Drive:=UpcaseStr(copy(Ref,1,P-1));  if Drive<>'' then  if (Drive='MAILTO') or (Drive='FTP') or (Drive='HTTP') or     (Drive='GOPHER') or (Drive='FILE') then    IsComplete:=true;  if IsComplete then S:=Ref else  begin    P:=Pos('#',Ref);    if P=0 then      Bookmark:=''    else      begin        Bookmark:=copy(Ref,P+1,length(Ref));        Ref:=copy(Ref,1,P-1);      end;    S:=CompletePath(Base,Ref);    if Bookmark<>'' then      S:=S+'#'+Bookmark;  end;  CompleteURL:=S;end;function OptimizePath(Path: string; MaxLen: integer): string;var i                : integer;    BackSlashs       : array[1..20] of integer;    BSCount          : integer;    Jobbra           : boolean;    Jobb, Bal        : byte;    Hiba             : boolean;begin if length(Path)>MaxLen then begin  BSCount:=0; Jobbra:=true;  for i:=1 to length(Path) do if Path[i]=DirSep then      begin        Inc(BSCount);        BackSlashs[BSCount]:=i;      end;  i:=BSCount div 2;  Hiba:=false;  Bal:=i; Jobb:=i+1;  case i of 0  : ;            1  : Path:=copy(Path, 1, BackSlashs[1])+'..'+                       copy(Path, BackSlashs[2], length(Path));            else begin                   while (BackSlashs[Bal]+(length(Path)-BackSlashs[Jobb]) >=                          MaxLen) and not Hiba do                         begin                           if Jobbra then begin                                           if Jobb<BSCount then inc(Jobb)                                                           else Hiba:=true;                                           Jobbra:=false;                                          end                                     else begin                                           if Bal>1 then dec(Bal)                                                    else Hiba:=true;                                           Jobbra:=true;                                          end;                         end;                   Path:=copy(Path, 1, BackSlashs[Bal])+'..'+                         copy(Path, BackSlashs[Jobb], length(Path));                 end;  end; end;  if length(Path)>MaxLen then  begin    i:=Pos('\..\',Path);    if i>0 then Path:=copy(Path,1,i-1)+'..'+copy(Path,i+length('\..\'),length(Path));  end; OptimizePath:=Path;end;function Now: longint;var D: DateTime;    W: word;    L: longint;begin  FillChar(D,sizeof(D),0);  GetDate(D.Year,D.Month,D.Day,W);  GetTime(D.Hour,D.Min,D.Sec,W);  PackTime(D,L);  Now:=L;end;function FormatDateTimeL(L: longint; const Format: string): string;var D: DateTime;begin  UnpackTime(L,D);  FormatDateTimeL:=FormatDateTime(D,Format);end;function FormatDateTime(const D: DateTime; const Format: string): string;var I: sw_integer;    CurCharStart: sw_integer;    CurChar: char;    CurCharCount: integer;    DateS: string;    C: char;procedure FlushChars;var S: string;    I: sw_integer;begin  S:='';  for I:=1 to CurCharCount do    S:=S+CurChar;  case CurChar of    'y' : S:=IntToStrL(D.Year,length(S));    'm' : S:=IntToStrZ(D.Month,length(S));    'd' : S:=IntToStrZ(D.Day,length(S));    'h' : S:=IntToStrZ(D.Hour,length(S));    'n' : S:=IntToStrZ(D.Min,length(S));    's' : S:=IntToStrZ(D.Sec,length(S));  end;  DateS:=DateS+S;end;begin  DateS:='';  CurCharStart:=-1; CurCharCount:=0; CurChar:=#0;  for I:=1 to length(Format) do  begin    C:=Format[I];    if (C<>CurChar) or (CurCharStart=-1) then      begin        if CurCharStart<>-1 then FlushChars;        CurCharCount:=1; CurCharStart:=I;      end    else      Inc(CurCharCount);    CurChar:=C;  end;  FlushChars;  FormatDateTime:=DateS;end;function DeleteFile(const FileName: string): integer;var f: file;begin{$I-}  Assign(f,FileName);  Erase(f);  DeleteFile:=EatIO;{$I+}end;function ExistsFile(const FileName: string): boolean;var  Dir : SearchRec;begin  Dos.FindFirst(FileName,Archive+ReadOnly,Dir);  ExistsFile:=(Dos.DosError=0);  Dos.FindClose(Dir);end;{ returns zero for empty and non existant files }function SizeOfFile(const FileName: string): longint;var  Dir : SearchRec;begin  Dos.FindFirst(FileName,Archive+ReadOnly,Dir);  if (Dos.DosError=0) then    SizeOfFile:=Dir.Size  else    SizeOfFile:=0;  Dos.FindClose(Dir);end;function ExistsDir(const DirName: string): boolean;var  Dir : SearchRec;begin  Dos.FindFirst(TrimEndSlash(DirName),Directory,Dir);  { if a file is found it is also reported    at least for some Dos version    so we need to check the attributes PM }  ExistsDir:=(Dos.DosError=0) and ((Dir.attr and Directory) <> 0);  Dos.FindClose(Dir);end;function CompleteDir(const Path: string): string;begin  { keep c: untouched PM }  if (Path<>'') and (Path[Length(Path)]<>DirSep) and     (Path[Length(Path)]<>':') then   CompleteDir:=Path+DirSep  else   CompleteDir:=Path;end;function GetCurDir: string;var S: string;begin  GetDir(0,S);  if copy(S,length(S),1)<>DirSep then S:=S+DirSep;  GetCurDir:=S;end;function GenTempFileName: string;var Dir: string;    Name: string;    I: integer;    OK: boolean;    Path: string;begin  Dir:=GetEnv('TEMP');  if Dir='' then Dir:=GetEnv('TMP');  if (Dir<>'') then if not ExistsDir(Dir) then Dir:='';  if Dir='' then Dir:=GetCurDir;  repeat    Name:=TempFirstChar;    for I:=2 to TempNameLen do      Name:=Name+chr(ord('a')+random(ord('z')-ord('a')+1));    Name:=Name+TempExt;    Path:=CompleteDir(Dir)+Name;    OK:=not ExistsFile(Path);  until OK;  GenTempFileName:=Path;end;function CopyFile(const SrcFileName, DestFileName: string): boolean;var SrcF,DestF: PBufStream;    OK: boolean;begin  SrcF:=nil; DestF:=nil;  New(SrcF, Init(SrcFileName,stOpenRead,4096));  OK:=Assigned(SrcF) and (SrcF^.Status=stOK);  if OK then  begin    New(DestF, Init(DestFileName,stCreate,1024));    OK:=Assigned(DestF) and (DestF^.Status=stOK);  end;  if OK then DestF^.CopyFrom(SrcF^,SrcF^.GetSize);  if Assigned(DestF) then Dispose(DestF, Done);  if Assigned(SrcF) then Dispose(SrcF, Done);  CopyFile:=OK;end;procedure RegisterWUtils;begin{$ifndef NOOBJREG}  RegisterType(RUnsortedStringCollection);{$endif}end;Procedure DebugMessage(AFileName, AText : string; ALine, APos : sw_word); // calls DebugMessagebegin  DebugMessageS(Afilename,AText,'','',aline,apos);end;Procedure WUtilsDebugMessage(AFileName, AText : string; ALine, APos : string;nrLine, nrPos : sw_word);begin  writeln(stderr,AFileName,' (',ALine,',',APos,') ',AText);  flush(stderr);end;BEGIN  Randomize;END.
 |