uEWOTAHelpers.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. unit uEWOTAHelpers;
  2. {$I eDefines.inc}
  3. interface
  4. uses
  5. {$IFDEF DELPHI5}ComObj,{$ENDIF}
  6. ToolsAPI, Classes;
  7. function GetDelphiVersion: Integer;
  8. function GetDllPath: String;
  9. function ModuleServices: IOTAModuleServices;
  10. function CurrentProject: IOTAProject;
  11. function ProjectByName(const aName: string): IOTAProject;
  12. function CurrentProjectGroup: IOTAProjectGroup;
  13. function GetUniqueProjectFilename(aProject: IOTAProject; aName: string): string;
  14. function FindModuleByUnitName(const aProject: IOTAProject; const aModuleName: string): IOTAModule;
  15. function RemoveInitialT(const aString:string):string;
  16. function AddInitialT(const aString:string):string;
  17. function ProjectName: string;
  18. function LoadStringFromFile(iFilename:string):string;
  19. procedure SaveStringToFile(const iFilename,iString:string);
  20. function ReplaceVariables(const aString: string; aVariables: TStrings): string;
  21. function ReadModuleSource(const aModule: IOTAModule): string;
  22. procedure WriteModuleSource(const aModule: IOTAModule; const aCode, aHeader: string);
  23. procedure AddOrReplaceNamedModule(const aProject: IOTAProject; aName, aCode: string);
  24. function LanguageFromPersonality(aProject: IOTAProject): string;
  25. function LanguageFromPersonalityEx(aProject: IOTAProject): string;
  26. implementation
  27. uses {$IFDEF MSWINDOWS}Windows, ActiveX, {$ENDIF} SysUtils, Forms, uEWHelpers;
  28. function LoadStringFromFile(iFilename:string):string;
  29. {$IFDEF DELPHI2009UP}
  30. begin
  31. With TStringList.Create do try
  32. LoadFromFile(iFilename);
  33. Result := Text;
  34. finally
  35. Free;
  36. end;
  37. end;
  38. {$ELSE}
  39. var t:text;
  40. s:string;
  41. begin
  42. try
  43. AssignFile(t,iFilename);
  44. Reset(t);
  45. try
  46. result := '';
  47. while not Eof(t) do begin
  48. Readln(t,s);
  49. result := result+s+#13#10;
  50. end;
  51. finally
  52. CloseFile(t);
  53. end;
  54. except
  55. on E:Exception do
  56. raise EInOutError.Create('Error loading file '+iFilename+' ('+E.ClassName+': '+E.Message+')');
  57. end;
  58. end;
  59. {$ENDIF}
  60. procedure SaveStringToFile(const iFilename,iString:string);
  61. {$IFDEF DELPHI2009UP}
  62. begin
  63. With TStringList.Create do try
  64. Text := iString;
  65. SaveToFile(iFilename);
  66. finally
  67. free;
  68. end;
  69. end;
  70. {$ELSE}
  71. var t:TextFile;
  72. begin
  73. try
  74. AssignFile(t,iFilename);
  75. Rewrite(t);
  76. try
  77. Write(t,iString);
  78. finally
  79. CloseFile(t);
  80. end;
  81. except
  82. on E:Exception do
  83. raise EInOutError.Create('Error saving file '+iFilename+' ('+E.ClassName+': '+E.Message+')');
  84. end;
  85. end;
  86. {$ENDIF}
  87. function NewGuid:TGUID;
  88. begin
  89. {$IFDEF MSWINDOWS}
  90. CoCreateGuid(result);
  91. {$ENDIF MSWINDOWS}
  92. {$IFDEF LINUX}
  93. CreateGuid(result);
  94. {$ENDIF}
  95. end;
  96. function NewGuidAsString:string;
  97. begin
  98. result := GuidToString(NewGuid());
  99. end;
  100. function NewGuidAsStringNoBrackets:string;
  101. begin
  102. result := GuidToString(NewGuid());
  103. result := Copy(result,2,Length(result)-2);
  104. end;
  105. function ReplaceVariables(const aString: string; aVariables: TStrings): string;
  106. var
  107. i:integer;
  108. begin
  109. { No, this isn't efficient code. But given the fact that this is used at designtime and
  110. in a place where the execution is abolutely not time-critical, clarity is preferable to
  111. efficiency, imho. mh. }
  112. result := aString;
  113. if Assigned(aVariables) then begin
  114. for i := 0 to aVariables.Count-1 do begin
  115. result := StringReplace(result,'$('+aVariables.Names[i]+')',aVariables.Values[aVariables.Names[i]],[rfReplaceAll,rfIgnoreCase]);
  116. end;
  117. end;
  118. result := StringReplace(result,'$(NewID)',NewGuidAsString(),[rfReplaceAll,rfIgnoreCase]);
  119. result := StringReplace(result,'$(NewID2)',NewGuidAsStringNoBrackets(),[rfReplaceAll,rfIgnoreCase]);
  120. end;
  121. function ProjectName: string;
  122. var
  123. lProjectName:string;
  124. begin
  125. if Assigned(CurrentProject()) then begin
  126. lProjectName := (CurrentProject as IOTAModule).FileName;
  127. lProjectName := ChangeFileExt(ExtractFileName(lProjectName),'');
  128. end
  129. else begin
  130. lProjectName := '';
  131. end;
  132. result := lProjectName;
  133. end;
  134. function RemoveInitialT(const aString:string):string;
  135. begin
  136. result := aString;
  137. if (result <> '') and (result[1] = 'T') then Delete(result,1,1);
  138. end;
  139. function AddInitialT(const aString:string):string;
  140. begin
  141. result := aString;
  142. if (result <> '') and (result[1] <> 'T') then result := 'T'+result;
  143. end;
  144. function GetDllPath: String;
  145. var TheFileName : array[0..MAX_PATH] of char;
  146. begin
  147. FillChar(TheFileName, SizeOf(TheFileName), #0);
  148. {$IFDEF KYLIX}System.{$ENDIF}GetModuleFileName(hInstance, TheFileName, sizeof(TheFileName));
  149. Result := ExtractFilePath(TheFileName);
  150. end;
  151. function ModuleServices: IOTAModuleServices;
  152. begin
  153. result := (BorlandIDEServices as IOTAModuleServices);
  154. end;
  155. function CurrentProject: IOTAProject;
  156. var
  157. services: IOTAModuleServices;
  158. module: IOTAModule;
  159. project: IOTAProject;
  160. projectgroup: IOTAProjectGroup;
  161. multipleprojects: Boolean;
  162. i: Integer;
  163. begin
  164. result := nil;
  165. multipleprojects := False;
  166. services := ModuleServices;
  167. if (services = nil) then Exit;
  168. for I := 0 to (services.ModuleCount - 1) do begin
  169. module := services.Modules[I];
  170. if (module.QueryInterface(IOTAProjectGroup, ProjectGroup) = S_OK) then begin
  171. result := ProjectGroup.ActiveProject;
  172. Exit;
  173. end
  174. else if module.QueryInterface(IOTAProject, Project) = S_OK then begin
  175. if (result = nil) then
  176. result := Project // Found the first project, so save it
  177. else
  178. multipleprojects := True; // It doesn't look good, but keep searching for a project group
  179. end;
  180. end;
  181. if multipleprojects then result := nil;
  182. end;
  183. function ProjectByName(const aName: string): IOTAProject;
  184. var
  185. services: IOTAModuleServices;
  186. module: IOTAModule;
  187. project: IOTAProject;
  188. i: Integer;
  189. begin
  190. result := nil;
  191. services := ModuleServices;
  192. if (services = nil) then Exit;
  193. for I := 0 to (services.ModuleCount - 1) do begin
  194. module := services.Modules[I];
  195. if module.QueryInterface(IOTAProject, Project) = S_OK then begin
  196. if module.FileName = aName then begin
  197. result := Project;
  198. exit;
  199. end;
  200. end;
  201. end;
  202. end;
  203. function CurrentProjectGroup: IOTAProjectGroup;
  204. var
  205. services: IOTAModuleServices;
  206. i: Integer;
  207. begin
  208. Result := nil;
  209. services := ModuleServices;
  210. for i := 0 to ModuleServices.ModuleCount - 1 do begin
  211. if Supports(ModuleServices.Modules[i], IOTAProjectGroup, Result) then begin
  212. Break;
  213. end;
  214. end;
  215. end;
  216. function GetUniqueProjectFilename(aProject: IOTAProject; aName: string): string;
  217. var
  218. lBaseName, lName: string;
  219. lCount: integer;
  220. function ProjectHasFile: boolean;
  221. var
  222. i: integer;
  223. begin
  224. result := false;
  225. for i := 0 to aProject.GetModuleCount-1 do begin
  226. if (aProject.GetModule(i).Name = lName) or (aProject.GetModule(i).Name = ChangeFileExt(lName, '')) then begin
  227. result := true;
  228. break;
  229. end;
  230. end;
  231. end;
  232. begin
  233. lName := aName;
  234. lBaseName := ChangeFileExt(aName, '');
  235. lCount := 0;
  236. while ProjectHasFile() do begin
  237. inc(lCount);
  238. lName := lBaseName+IntToStr(lCount)+ExtractFileExt(aName);
  239. end;
  240. result := lName;
  241. end;
  242. function FindModuleByUnitName(const aProject: IOTAProject; const aModuleName: string): IOTAModule;
  243. var
  244. i: integer;
  245. begin
  246. result := nil;
  247. for i := 0 to aProject.GetModuleCount - 1 do
  248. if (CompareText(ExtractFileName(aModuleName), ExtractFileName(aProject.GetModule(i).FileName)) = 0) then begin
  249. result := aProject.GetModule(i).OpenModule;
  250. Exit;
  251. end;
  252. end;
  253. const
  254. MaxSourceSize = 10000;
  255. function ReadModuleSource(const aModule: IOTAModule): String;
  256. var
  257. l, i: integer;
  258. editor: IOTASourceEditor;
  259. reader: IOTAEditReader;
  260. lSource: AnsiString;
  261. begin
  262. result := '';
  263. with aModule do
  264. for i := 0 to GetModuleFileCount - 1 do begin
  265. if Supports(GetModuleFileEditor(i), IOTASourceEditor, editor) then begin
  266. // TODO: find a way not to depend on files smaller than 10k... I only use this for DPRs so it's fine for now
  267. SetLength(lSource, MaxSourceSize);
  268. //l := 0; to remove warning
  269. reader := editor.CreateReader;
  270. l := reader.GetText(0, @lSource[1], MaxSourceSize);
  271. reader := nil;
  272. SetLength(lSource, l);
  273. result := {$IFDEF DELPHI2009UP}UTF8ToString{$ENDIF}(lSource);
  274. Exit;
  275. end;
  276. end;
  277. end;
  278. procedure WriteModuleSource(const aModule: IOTAModule; const aCode, aHeader: string);
  279. var
  280. i: integer;
  281. lEditor: IOTASourceEditor;
  282. writer: IOTAEditWriter;
  283. begin
  284. with aModule do begin
  285. for i := 0 to GetModuleFileCount - 1 do begin
  286. if Supports(GetModuleFileEditor(i), IOTASourceEditor, lEditor) then begin
  287. if LowerCase(ExtractFileExt(GetModuleFileEditor(i).FileName)) = '.h' then begin
  288. if aHeader <> '' then begin
  289. writer := lEditor.CreateWriter;
  290. writer.DeleteTo(MaxInt);
  291. writer.Insert(PAnsiChar({$IFDEF DELPHI2009UP}UTF8Encode{$ENDIF}(aHeader)));
  292. writer := nil;
  293. end;
  294. end
  295. else begin
  296. writer := lEditor.CreateWriter;
  297. writer.DeleteTo(MaxInt);
  298. writer.Insert(PAnsiChar({$IFDEF DELPHI2009UP}UTF8Encode{$ENDIF}(aCode)));
  299. writer := nil;
  300. end;
  301. end;
  302. end;
  303. end;
  304. end;
  305. procedure AddOrReplaceNamedModule(const aProject: IOTAProject; aName, aCode: string);
  306. var
  307. lModule: IOTAModule;
  308. begin
  309. lModule := FindModuleByUnitName(aProject, aName);
  310. if assigned(lModule) then begin
  311. WriteModuleSource(lModule, aCode, '');
  312. end
  313. else begin
  314. aName := ExtractFilePath(CurrentProject.FileName)+aName;
  315. SaveStringToFile(aName, aCode);
  316. CurrentProject.AddFile(aName, true);
  317. lModule := FindModuleByUnitName(CurrentProject, aName);
  318. {$IFDEF DELPHI9UP}
  319. if assigned(lModule) then lModule.Show();
  320. {$ENDIF DELPHI9UP}
  321. end;
  322. end;
  323. function GetDelphiVersion: Integer;
  324. begin
  325. {$IFDEF DELPHI5}
  326. result := 5;
  327. {$ELSE}
  328. {$IFDEF DELPHI2007}
  329. result := 11;
  330. {$ELSE}
  331. {$IFDEF DELPHI2010}
  332. result := 14;
  333. {$ELSE}
  334. {$IFDEF DELPHI2011}
  335. result := 15;
  336. {$ELSE}
  337. {$IFDEF DELPHIXE2}
  338. result := 16;
  339. {$ELSE}
  340. {$IFDEF DELPHIXE3}
  341. result := 17;
  342. {$ELSE}
  343. {$IFDEF DELPHIXE4}
  344. result := 18;
  345. {$ELSE}
  346. {$IFDEF DELPHIXE5}
  347. result := 19;
  348. {$ELSE}
  349. result := Trunc(RTLVersion)-8;
  350. {$ENDIF}
  351. {$ENDIF}
  352. {$ENDIF}
  353. {$ENDIF}
  354. {$ENDIF}
  355. {$ENDIF}
  356. {$ENDIF}
  357. {$ENDIF}
  358. end;
  359. function LanguageFromPersonality(aProject: IOTAProject): string;
  360. {$IFDEF BDS}
  361. var s: string;
  362. {$ENDIF}
  363. begin
  364. {$IFDEF BDS}
  365. s := aProject.Personality;
  366. if s = sDelphiPersonality then result := 'Delphi for Win32'
  367. else if s = sDelphiDotNetPersonality then result := 'Delphi for .NET'
  368. else if s = sCSharpPersonality then result := 'C#'
  369. else if s = sVBPersonality then result := 'Visual Basic'
  370. else if s = sCBuilderPersonality then result := 'C++'
  371. else result := 'Unknown';
  372. {$ELSE}
  373. result := 'Delphi for Win32';
  374. {$ENDIF}
  375. end;
  376. function LanguageFromPersonalityEx(aProject: IOTAProject): string;
  377. begin
  378. result := LanguageFromPersonality(aProject);
  379. {$IFDEF BDS}
  380. if result = 'Delphi for .NET' then
  381. result := result+'/'+IntToStr(GetDelphiVersion);
  382. {$ENDIF}
  383. end;
  384. end.