mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-10-26 16:22:04 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			286 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			286 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| {%MainUnit lazutf8.pas}
 | |
| 
 | |
| var
 | |
|   //Function prototypes
 | |
|   _ParamStrUtf8: Function(Param: Integer): string;
 | |
| 
 | |
| var
 | |
|   ArgsW: Array of WideString;
 | |
|   ArgsWCount: Integer;
 | |
| 
 | |
| //************ START "Stubs" that just call Ansi or Wide implementation
 | |
| 
 | |
| function ParamStrUTF8(Param: Integer): string;
 | |
| begin
 | |
|   Result := _ParamStrUtf8(Param);
 | |
| end;
 | |
| 
 | |
| //************ END "Stubs" that just call Ansi or Wide implementation
 | |
| 
 | |
| 
 | |
| //*************** START Non WideString implementations
 | |
| {$ifndef wince}
 | |
| function ParamStrUtf8Ansi(Param: Integer): String;
 | |
| begin
 | |
|   Result:=SysToUTF8(ObjPas.ParamStr(Param));
 | |
| end;
 | |
| {$endif wince}
 | |
| 
 | |
| //*************** END Non WideString impementations
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| //*************** START WideString impementations
 | |
| 
 | |
| //fpc 2.6.0 does not have StrLen for WideChar.
 | |
| //Remove this when we have 2.6.4 or higher
 | |
| {$if FPC_FULLVERSION < 20602}
 | |
| function StrLen(PW: PWideChar): SizeInt; overload;
 | |
| var
 | |
|   i: SizeInt;
 | |
| begin
 | |
|   i:=0;
 | |
|   if assigned(PW) then
 | |
|     while (PW[i] <> #0) do inc(i);
 | |
|   Result := i;
 | |
| end;
 | |
| {$endif}
 | |
| 
 | |
| 
 | |
| procedure SetupCommandlineParametersWide;
 | |
| var
 | |
|   ArgLen, Start, CmdLen, i, j: SizeInt;
 | |
|   Quote   : Boolean;
 | |
|   Buf: array[0..259] of WChar;  // need MAX_PATH bytes, not 256!
 | |
|   PCmdLineW: PWideChar;
 | |
|   CmdLineW: WideString;
 | |
| 
 | |
|   procedure AllocArg(Idx, Len:longint);
 | |
|   begin
 | |
|     if (Idx >= ArgsWCount) then
 | |
|     begin
 | |
|       SetLength(ArgsW, Idx + 1);
 | |
|       SetLength(ArgsW[Idx], Len);
 | |
|     end;
 | |
|   end;
 | |
| 
 | |
| 
 | |
| begin
 | |
|   { create commandline, it starts with the executed filename which is argv[0] }
 | |
|   { Win32 passes the command NOT via the args, but via getmodulefilename}
 | |
|   ArgsWCount := 0;
 | |
|   ArgLen := GetModuleFileNameW(0, @buf[0], sizeof(buf));
 | |
| 
 | |
|   //writeln('ArgLen = ',Arglen);
 | |
| 
 | |
|   buf[ArgLen] := #0; // be safe, no terminating 0 on XP
 | |
|   allocarg(0,arglen);
 | |
|   move(buf[0],ArgsW[0][1],arglen * SizeOf(WChar));
 | |
| 
 | |
|   //writeln('ArgsW[0] = ',ArgsW[0]);
 | |
| 
 | |
|   PCmdLineW := nil;
 | |
|   { Setup cmdline variable }
 | |
|   PCmdLineW := GetCommandLineW;
 | |
|   CmdLen := StrLen(PCmdLineW);
 | |
| 
 | |
|   //writeln('StrLen(PCmdLineW) = ',CmdLen);
 | |
| 
 | |
|   SetLength(CmdLineW, CmdLen);
 | |
|   Move(PCmdLineW^, CmdLineW[1], CmdLen * SizeOf(WChar));
 | |
| 
 | |
| 
 | |
|   //debugln(CmdLineW);
 | |
|   //for i := 1 to CmdLen do DbgOut(DbgS(i mod 10)); debugln;
 | |
| 
 | |
|   i := 1;
 | |
|   while (i <= CmdLen) do
 | |
|   begin
 | |
|     //debugln('Next');
 | |
|     //DbgOut('i=',DbgS(i),' CmdLineW[',DbgS(i),']=');if i<=CmdLen then debugln(CmdLineW[i]) else debugln('#0');
 | |
|     //skip leading spaces
 | |
|     while (i <= CmdLen) and (CmdLineW[i] <= #32) do Inc(i);
 | |
|     //DbgOut('After skipping spaces: i=',DbgS(i),' CmdLineW[',DbgS(i),']=');if i<=CmdLen then debugln(CmdLineW[i]) else debugln('#0');
 | |
|     if (i > CmdLen) then Break;
 | |
|     Quote := False;
 | |
|     Start := i;
 | |
|     ArgLen := 0;
 | |
|     while (i <= CmdLen) do
 | |
|     begin //find next commandline parameter
 | |
|       case CmdLineW[i] of
 | |
|         #1..#32:
 | |
|         begin
 | |
|           if Quote then
 | |
|           begin
 | |
|             //debugln('i=',DbgS(i),': Space in Quote');
 | |
|             Inc(ArgLen)
 | |
|           end
 | |
|           else
 | |
|           begin
 | |
|             //debugln('i=',DbgS(i),': Space in NOT Quote');
 | |
|             Break;
 | |
|           end;
 | |
|         end;
 | |
|         '"':
 | |
|         begin
 | |
|           if (i < CmdLen) and (CmdLineW[i+1] <> '"') then
 | |
|           begin
 | |
|             //debugln('i=',DbgS(i),': Quote := not Quote');
 | |
|             Quote := not Quote
 | |
|           end
 | |
|           else
 | |
|           begin
 | |
|             //debugln('i=',DbgS(i),': Skip Quote');
 | |
|             Inc(i);
 | |
|           end;
 | |
|         end;
 | |
|         else Inc(ArgLen);
 | |
|       end;//case
 | |
|       Inc(i);
 | |
| 
 | |
| 
 | |
|     end; //find next commandline parameter
 | |
| 
 | |
|     //debugln('ArgWCount=',DbgS(ArgsWCount),' Start=',DbgS(start),' ArgLen=',DbgS(arglen),' i=',DbgS(i));
 | |
| 
 | |
|     //we already have (a better) ArgW[0]
 | |
|     if (ArgsWCount > 0) then
 | |
|     begin //Process commadline parameter
 | |
|       AllocArg(ArgsWCount, ArgLen);
 | |
|       Quote := False;
 | |
|       i := Start;
 | |
|       j := 1;
 | |
|       while (i <= CmdLen) do
 | |
|       begin
 | |
|         case CmdLineW[i] of
 | |
|           #1..#32:
 | |
|           begin
 | |
|             if Quote then
 | |
|             begin
 | |
|               //if j > ArgLen then debugln('Error whitespace: j > ArgLen: j=',DbgS(j),' ArgLen=',DbgS(arglen));
 | |
|               ArgsW[ArgsWCount][j] := CmdLineW[i];
 | |
|               Inc(j);
 | |
|             end
 | |
|             else
 | |
|               Break;
 | |
|           end;
 | |
|           '"':
 | |
|           begin
 | |
|             if (i < CmdLen) and (CmdLineW[i+1] <> '"') then
 | |
|               Quote := not Quote
 | |
|             else
 | |
|               Inc(i);
 | |
|           end;
 | |
|           else
 | |
|           begin
 | |
|             //if j > ArgLen then debugln('Error Quote: j > ArgLen: j=',DbgS(j),' ArgLen=',DbgS(arglen));
 | |
|             ArgsW[ArgsWCount][j] := CmdLineW[i];
 | |
|             Inc(j);
 | |
|           end;
 | |
|         end;
 | |
|         Inc(i);
 | |
|       end;
 | |
| 
 | |
|       //debugln('ArgsW[',DbgS(ArgsWCount),'] = ',ArgsW[ArgsWCount]);
 | |
|     end; // Process commandline parameter
 | |
|     Inc(ArgsWCount);
 | |
| 
 | |
|   end;
 | |
|   Dec(ArgsWCount);
 | |
| end;
 | |
| 
 | |
| function ParamStrUtf8Wide(Param: Integer): String;
 | |
| begin
 | |
|   if ArgsWCount <> ParamCount then
 | |
|   begin
 | |
|     //DebugLn('Error: ParamCount <> ArgsWCount!');
 | |
|     Result := SysToUtf8(ObjPas.ParamStr(Param));
 | |
|   end
 | |
|   else
 | |
|   begin
 | |
|     if (Param <= ArgsWCount) then
 | |
|       Result := Utf8Encode(ArgsW[Param])
 | |
|     else
 | |
|       Result := '';
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| //*************** END WideString impementations
 | |
| 
 | |
| 
 | |
| 
 | |
| function ConsoleToUTF8(const s: string): string;// converts UTF8 string to console encoding (used by Write, WriteLn)
 | |
| var
 | |
|   Dst: PChar;
 | |
| begin
 | |
|   {$ifdef WinCE}
 | |
|   Result := SysToUTF8(s);
 | |
|   {$else}
 | |
|   Dst := AllocMem((Length(s) + 1) * SizeOf(Char));
 | |
|   if OemToChar(PChar(s), Dst) then
 | |
|     Result := StrPas(Dst)
 | |
|   else
 | |
|     Result := s;
 | |
|   FreeMem(Dst);
 | |
|   Result := SysToUTF8(Result);
 | |
|   {$endif}
 | |
| end;
 | |
| 
 | |
| function UTF8ToConsole(const s: string): string;
 | |
| var
 | |
|   Dst: PChar;
 | |
| begin
 | |
|   {$ifdef WinCE}
 | |
|   Result := UTF8ToSys(s);
 | |
|   {$else}
 | |
|   Result := UTF8ToSys(s);
 | |
|   Dst := AllocMem((Length(Result) + 1) * SizeOf(Char));
 | |
|   if CharToOEM(PChar(Result), Dst) then
 | |
|     Result := StrPas(Dst);
 | |
|   FreeMem(Dst);
 | |
|   {$endif}
 | |
| end;
 | |
| 
 | |
| {$ifdef debugparamstrutf8}
 | |
| procedure ParamStrUtf8Error;
 | |
| var
 | |
|   i: Integer;
 | |
| begin
 | |
|   writeln('Error in Windows WideString implementation of ParamStrUtf8');
 | |
|   writeln('Using SysToUtf8(ParamsStr(Param)) as fallback');
 | |
|   writeln('ParamCount = ',ParamCount,', ArgsWCount = ',ArgsWCount);
 | |
|   for i := 0 to ParamCount do writeln('ParamStr(',i,') = "',ParamStr(i),'"');
 | |
|   writeln;
 | |
|   for i := 0 to ArgsWCount do writeln('ParamStrUtf8(',i,') = "',ArgsW[i],'"');
 | |
| end;
 | |
| {$endif}
 | |
| 
 | |
| procedure InitLazUtf8;
 | |
| begin
 | |
|   {$ifndef WinCE}
 | |
|   if Win32MajorVersion <= 4 then
 | |
|   begin
 | |
|     _ParamStrUtf8 := @ParamStrUtf8Ansi;
 | |
|   end
 | |
|   else
 | |
|   {$endif}
 | |
|   begin
 | |
|     try
 | |
|       ArgsWCount := -1;
 | |
|       _ParamStrUtf8 := @ParamStrUtf8Wide;
 | |
|       SetupCommandlineParametersWide;
 | |
|       {$ifdef debugparamstrutf8}
 | |
|       if ParamCount <> ArgsWCount then ParamStrUtf8Error;
 | |
|       {$endif}
 | |
|     Except
 | |
|       begin
 | |
|         ArgsWCount := -1;
 | |
|         {$ifdef debugparamstrutf8}
 | |
|         ParamStrUtf8Error;
 | |
|         {$endif}
 | |
|       end;
 | |
|     end;
 | |
|   end;
 | |
| end;
 | 
