/packages/winunits-base/src/win9xwsmanager.pp

https://github.com/slibre/freepascal · Puppet · 215 lines · 180 code · 35 blank · 0 comment · 21 complexity · f96338dbb7dceabc167b5206deb7cac3 MD5 · raw file

  1. { *********************************************************************
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2011 by Bart Broersma.
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
  9. **********************************************************************}
  10. unit win9xwsmanager;
  11. {**********************************************************************
  12. Objective: to provide minimal WideString Upper- and LowerCase
  13. functionality under Win9x systems.
  14. This is achievd by dynamically linking shlwapi.dll functions.
  15. If this fails a fallback mechanism is provided so that at least all
  16. lower ASCII characters in a WideString are Upper/LowerCased
  17. Without this library UTF8UpperCase/UTF8LowerCase will fail
  18. on win9x systems (which makes many Lazarus LCL controls that
  19. handle strings behave wrong).
  20. You can use this unit in your uses clause independent of yout target OS.
  21. No code will be linked in if yout target is not Windows.
  22. On true Unicode Windows (WinCE, WinNT-based) no additional libraries
  23. will be linked in (see: InitWin9xWSManager).
  24. Currently only LowerWideStringProc and UpperWideStringProc are
  25. replaced on win9x.
  26. Possibly other functions might need replacin too.
  27. ***********************************************************************}
  28. {$mode objfpc}{$H+}
  29. interface
  30. {$IFDEF WINDOWS}
  31. { $define DEBUG_WIN9X_WSMANAGER}
  32. uses
  33. Windows, SysUtils;
  34. {$endif WINDOWS}
  35. implementation
  36. {$ifdef WINDOWS}
  37. type
  38. TShlwapiFunc = function(lpsz: LPWSTR; ccLength: DWORD): DWORD; stdcall;
  39. var
  40. CharUpperBuffWrapW: TShlwapifunc = nil;
  41. CharLowerBuffWrapW: TShlwapifunc = nil;
  42. ShlwapiHandle: THandle = 0;
  43. SavedUnicodeStringManager: TUnicodeStringManager;
  44. // Win9x**Simple functions do essentially Upper/LowerCase on
  45. // lower ASCII characters in the string
  46. function Win9xWideUpperSimple(const S: WideString): WideString;
  47. const
  48. diff = Ord('a') - Ord('A');
  49. var
  50. W: WideChar;
  51. i: Integer;
  52. begin
  53. Result := S;
  54. for i := 1 to length(Result) do
  55. begin
  56. W := Result[i];
  57. if (Ord(W) in [Ord(Char('a'))..Ord(Char('z'))]) then
  58. begin
  59. Word(W) := Word(W) - diff;
  60. Result[i] := W;
  61. end;
  62. end;
  63. end;
  64. function Win9xWideLowerSimple(const S: WideString): WideString;
  65. const
  66. diff = Ord('a') - Ord('A');
  67. var
  68. W: WideChar;
  69. i: Integer;
  70. begin
  71. Result := S;
  72. for i := 1 to length(Result) do
  73. begin
  74. W := Result[i];
  75. if (Ord(W) in [Ord(Char('A'))..Ord(Char('Z'))]) then
  76. begin
  77. Word(W) := Word(W) + diff;
  78. Result[i] := W;
  79. end;
  80. end;
  81. end;
  82. function Win9xWideUpper(const S: WideString): WideString;
  83. begin
  84. Result := S;
  85. CharUpperBuffWrapW(PWChar(Result), Length(Result));
  86. end;
  87. function Win9xWideLower(const S: WideString): WideString;
  88. begin
  89. Result := S;
  90. CharLowerBuffWrapW(PWChar(Result), Length(Result));
  91. end;
  92. procedure FreeDll;
  93. begin
  94. {$ifdef DEBUG_WIN9X_WSMANAGER}
  95. if IsConsole then writeln('FreeDLL');
  96. {$endif}
  97. if ShlwapiHandle <> 0 then
  98. begin
  99. FreeLibrary(ShlwapiHandle);
  100. ShlwapiHandle := 0;
  101. end;
  102. end;
  103. procedure InitDll;
  104. var
  105. PU,PL: Pointer;
  106. begin
  107. ShlwapiHandle := LoadLibrary('shlwapi.dll');
  108. if (ShlwapiHandle <> 0) then
  109. begin
  110. //shlwapi functions cannot be loaded by name, only by index!
  111. PU := GetProcAddress(ShlwapiHandle,PChar(44));
  112. if (PU <> nil) then CharUpperBuffWrapW := TShlwapiFunc(PU);
  113. PL := GetProcAddress(ShlwapiHandle,PChar(39));
  114. if (PL <> nil) then CharLowerBuffWrapW := TShlwapiFunc(PL);
  115. {$ifdef DEBUG_WIN9X_WSMANAGER}
  116. {$PUSH}{$HINTS OFF} //suppress hints on Pointer to PtrUInt tyecasting
  117. if IsConsole then
  118. begin
  119. writeln('Successfully loaded shlwapi.dll');
  120. if (PU <> nil) then
  121. writeln('Assigning CharUpperBuffWrapW @: ',HexStr(PtrUInt(PU),2*sizeof(PtrInt)))
  122. else
  123. writeln('Unable to load CharUpperBuffWrapW');
  124. if (PL <> nil) then
  125. writeln('Assigning CharLowerBuffWrapW @: ',HexStr(PtrUInt(PL),2*sizeof(PtrInt)))
  126. else
  127. writeln('Unable to load CharLowerBuffWrapW');
  128. end;
  129. {$POP}
  130. {$endif DEBUG_WIN9X_WSMANAGER}
  131. if (PU = nil) and (PL = nil) then
  132. begin
  133. FreeDLL;
  134. end;
  135. end
  136. else
  137. begin
  138. {$ifdef DEBUG_WIN9X_WSMANAGER}
  139. writeln('Unable to load shlwapi.dll');
  140. {$endif}
  141. end;
  142. end;
  143. procedure InitWin9xWSManager;
  144. var
  145. WS: WideString;
  146. begin
  147. SavedUnicodeStringManager := WideStringManager;
  148. WS := 'abc';
  149. if WideUpperCase(WS) <> 'ABC' then
  150. begin
  151. InitDLL;
  152. if Assigned(CharUpperBuffWrapW) then
  153. begin
  154. WideStringManager.UpperWideStringProc := @Win9xWideUpper;
  155. WS := 'abc';
  156. if WideUpperCase(WS) <> 'ABC' then WideStringManager.UpperWideStringProc := @Win9xWideUpperSimple;
  157. end
  158. else
  159. begin
  160. WideStringManager.UpperWideStringProc := @Win9xWideUpperSimple;
  161. end;
  162. if Assigned(CharLowerBuffWrapW) then
  163. begin
  164. WideStringmanager.LowerWideStringProc := @Win9xWideLower;
  165. WS := 'ABC';
  166. if WideLowerCase(WS) <> 'abc' then WideStringManager.LowerWideStringProc := @Win9xWideLowerSimple;
  167. end
  168. else
  169. begin
  170. WideStringManager.LowerWideStringProc := @Win9xWideLowerSimple;
  171. end;
  172. end;
  173. end;
  174. initialization
  175. InitWin9xWSManager;
  176. finalization
  177. WideStringManager := SavedUnicodeStringManager;
  178. if (ShlwapiHandle <> 0) then FreeDll;
  179. {$endif}
  180. end.