UnitMainBackend: Move ListProgramsOnDisc to this unit and clean it up a bit.
[WineLauncher.git] / Functions / Misc / UnitMisc.pas
blob2394d53ae12cec2a91984275a5ca04bb8cd80465
1 { This file is part of WineLauncher.
3 WineLauncher is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, version 3 of the License.
7 WineLauncher is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with WineLauncher. If not, see <http://www.gnu.org/licenses/>.
16 unit UnitMisc;
18 {$mode objfpc}{$H+}
20 interface
22 uses
23 Classes, SysUtils, strutils, BaseUnix, Process, StdCtrls, FileUtil, Graphics;
25 procedure Log(Level:integer; Channel:string; LogText:string);
26 {$IFDEF LogVar}
27 procedure LogVar(MyVar:string; MyVarName:string);
28 {$ENDIF}
30 function Wrap(Input:string):string; { Makes Paths look better, E.G. " ( Input ) " }
31 function WinToUnixPath(Path:string):string;
32 function UnixToWinPath(Path:string; DriveChar:Char):string;
33 function GetUnixDirPath(FilePath:string):string;
34 function FileExistsAndIsExecutable(FullPath:string; JustCheckExists:boolean): boolean ;
35 function WorkDirTemplate(FolderPath:string):string;
36 function DoesFolderExists(Path:string; FolderName:string): boolean;
37 function DoesFoldersExists(Path:string; FolderNames:Tstrings): boolean;
38 function DirExistsIfNotMakeIt(Path:string; FolderName:string ): boolean;
39 function DirExistsIfNotMakeIt(PathWithFolder:string): boolean;
40 function CheckPaths():boolean;
41 function SetupGit():boolean;
42 function MakeFile(FullPath:string;Data:string):boolean;
43 function SetExecutableFlag(FullPath:string):boolean;
44 function ColourCheck(Input: TEdit):boolean;
45 function CutUpFlags(Flags:string):boolean;
46 function FindPrefixInt(PrefixName:string):integer;
47 function GetWinFileName(FullPath:string):string;
49 //var
51 implementation
52 uses
53 UnitInitialization,
54 UnitMain,
55 UnitSettings,
56 UnitProgramsList;
58 function FileExistsAndIsExecutable(FullPath:string; JustCheckExists:boolean): boolean ;
59 var
60 ChannelLocal:string;
61 begin
62 ChannelLocal := ('FileExistsAndIsExecutable');
64 if JustCheckExists = true then
65 begin
66 if FileExists(FullPath) then
67 begin
68 {$IFDEF MoreTrue }
69 if JustCheckExists = true then Log(3, ChannelLocal, 'File' + Wrap(FullPath) + 'exists.');
70 {$ENDIF}
71 Result := true;
72 end
73 else
74 begin
75 Log(4, ChannelLocal,'File' + Wrap(FullPath) + 'does not exists.');
76 Result := false;
77 end;
78 end
79 else
80 begin
81 if FpAccess(FullPath, X_OK {Exe flag check}) <> 0 then
82 begin
83 Log(4, ChannelLocal,'File' + Wrap(FullPath) + 'is not executable.');
84 Result := false;
85 end
86 else
87 begin
88 {$IFDEF MoreTrue }
89 Log(3, ChannelLocal,'File' + Wrap(FullPath) + 'is executable.');
90 {$ENDIF}
91 Result := true;
92 end;
94 end;
95 end;
97 function Wrap(Input: string):string;
98 begin
99 Result := ( ' ( ' + Input + ' ) ' );
100 end;
102 function DoesFoldersExists(Path:string; FolderNames:Tstrings): boolean;
104 loop:integer;
105 begin
106 Result := true;
107 { Take a path and check to see if the listed folders exists in that path. }
108 { TODO : Add a way to check the result from each one and return it. }
109 for loop := 0 to ( FolderNames.Count - 1 ) do
110 begin
111 if DoesFolderExists(Path, FolderNames[loop]) = false then
112 begin
113 Result := false;
114 Exit;
115 end;
116 end;
117 end;
119 function DoesFolderExists(Path:string; FolderName:string): boolean;
121 ChannelLocal:string;
122 begin
123 ChannelLocal := 'DoesFolderExists';
124 if DirectoryExists(Path + FolderName) = true then
125 begin
126 Result := true ;
127 {$IFDEF MoreTrue }
128 UnitMain.form1.LogWithDebug(3, ChannelLocal, ('Folder' + Wrap(Path + FolderName) + 'exists.'));
129 {$ENDIF}
131 else
132 begin
133 Result := false ;
134 Log(4, ChannelLocal, ('Folder' + Wrap(Path + FolderName) + 'does not exists.'));
135 end;
136 end;
138 procedure Log(Level:integer; Channel:string; LogText:string);
140 LevelString:string;
141 OutPut:string;
142 begin
143 {Level 0 "Info"}
144 {Level 1 "Error"}
145 {Level 2 "Variable"}
146 {Level 3 "Dev-Info"}
147 {Level 4 "Dev-Error"}
148 {Level 5 is for uses with custom functions.}
150 Case Level of
151 0: LevelString := 'Info';
152 1: LevelString := 'Error';
153 2: LevelString := 'Variable';
154 3: LevelString := 'Dev-Info';
155 4: LevelString := 'Dev-Error';
156 end;
158 if Level = 5 then
159 begin
160 OutPut := (LogText);
162 else
163 begin
164 if HideChannel = true then
165 begin
166 OutPut := (LevelString + ': ' + LogText);
168 else
169 begin
170 OutPut := (LevelString + ':' + Channel + ': ' + LogText);
171 end;
172 end;
173 {Output}
174 WriteLn(OutPut);
175 if UnitMain.form1 <> nil then
176 begin
177 UnitMain.form1.Memo_LogOutPut.Lines.Add(OutPut);
178 end;
179 end;
181 function WinToUnixPath(Path:string):string;
183 PathUpToDosdevices:string;
184 DriveNameWithSlash:string;
185 FullUnixPath:string;
186 begin
187 {Get the path up to Dosdevices.}
188 PathUpToDosdevices := (GetEnvironmentVariable('HOME') + '/' + WineUserFolder + '/prefix/' + UnitMain.form1.ComboBox_PreFix.Text + '/dosdevices/' );
189 {Take the DriveName off 'path' and replace '\' with '/'.}
190 DriveNameWithSlash := (AnsiLowerCase( Copy2SymbDel( Path, '\' )) + '/');
191 {Replace all '\' to '/'.}
192 Path := AnsiReplaceText(Path, '\', '/');
193 {Sort then.}
194 FullUnixPath := (PathUpToDosdevices + DriveNameWithSlash + Path);
195 {$IFDEF LogVar}
196 {$IFDEF MOREDEBUG_WinToUnixPath}
197 logVar(PathUpToDosdevices, 'PathUpToDosdevices');
198 logVar(DriveNameWithSlash, 'DriveNameWithSlash');
199 logVar(Path, 'Path');
200 {$ENDIF}
201 logVar(FullUnixPath, 'FullUnixPath');
202 {$ENDIF}
203 Result := FullUnixPath;
205 end;
208 function UnixToWinPath(Path:string; DriveChar:Char):string;
210 WindowsFilePath :string;
211 SmallPath:string;
212 Cleanup:string;
213 begin
214 if Path = '' then
215 begin
216 Result := '';
217 exit;
218 end;
220 Path := AnsiReverseString(Path);
221 SmallPath := Copy2SymbDel(Path, ':');
222 SmallPath := AnsiReverseString(SmallPath);
223 Cleanup := AnsiReplaceText(SmallPath, '/', '\');
224 WindowsFilePath := (DriveChar + ':' + Cleanup);
226 {$IFDEF LogVar}
227 logVar(WindowsFilePath, 'WindowsFilePath');
228 {$ENDIF}
229 Result := WindowsFilePath;
230 end;
233 function GetUnixDirPath(FilePath:string):string;
235 DirPath:string;
236 //LocalChannel:string;
237 begin
238 DirPath := LeftStr(FilePath, (Rpos('/',FilePath) ));
239 //log(0, LocalChannel, ( 'VAR ' + DirPath));
241 Result := DirPath;
242 end;
244 function WorkDirTemplate(FolderPath:string):string;
245 begin
246 Result := ('cd "' + FolderPath + '";' + #10 );
247 end;
249 {$IFDEF LogVar}
250 procedure LogVar(MyVar: string; MyVarName: string);
251 begin
252 Log(2, 'LogVar', ( Wrap( MyVarName ) + 'is' + Wrap( MyVar )) );
253 end;
254 {$ENDIF}
256 function CheckPaths():boolean;
257 begin
259 Result := true;
261 if DirExistsIfNotMakeIt(GetEnvironmentVariable('HOME'), '/.config') <> true then
262 begin
263 Result := false;
264 end;
266 if DirExistsIfNotMakeIt(ConfigPath) <> true then
267 begin
268 Result := false;
269 end;
272 if DirExistsIfNotMakeIt(GetEnvironmentVariable('HOME') + '/' , WineUserFolder) = false then
273 begin
274 Result := false;
275 end;
277 if DirExistsIfNotMakeIt(GetEnvironmentVariable('HOME') + '/' + WineUserFolder + '/', 'prefix') = false then
278 begin
281 else
282 begin
283 if DoesFolderExists(GetEnvironmentVariable('HOME') + '/' + WineUserFolder + '/', 'git') = false then
284 begin
285 SetupGit();
286 end;
287 end;
290 if DirExistsIfNotMakeIt(GetEnvironmentVariable('HOME') + '/' + WineUserFolder + '/', 'wine') = false then
291 begin
292 Result := false;
293 end;
298 end;
301 function SetupGit():boolean;
303 Process:TProcess;
304 script:string;
305 RunYes:boolean;
306 ChannelLocal:string;
307 Terminal:string;
308 begin
309 Process := TProcess.Create(nil);
310 RunYes := true ;
311 ChannelLocal := 'SetupGit';
313 script := '#! /bin/sh' +{linebrake}#10 +
314 'echo This script will fetch Wine and compile it. ;'+{linebrake}#10 +
315 'echo If it fails please install the dependencies and rerun WineLauncher, see http://wiki.winehq.org/Recommended_Packages for more help.' +{linebrake}#10 +
316 'cd ' + GetEnvironmentVariable('HOME') + '/' + WineUserFolder + ' ;' +{linebrake}#10 +
317 'git clone git://source.winehq.org/git/wine.git git ;' +{linebrake}#10 +
318 'cd ./git ;' +{linebrake}#10 +
319 'git checkout -b stable-1.0.1 wine-1.0.1 ;' +{linebrake}#10 +
320 'Dname=`lsb_release -si` ;' +{linebrake}#10 +
321 'Dversion=`lsb_release -sr` ;' +{linebrake}#10 +
322 'Aname=`uname -m` ;' +{linebrake}#10 +
323 './configure --prefix=' + GetEnvironmentVariable('HOME') + '/' + WineUserFolder + '/wine/$Dname/$Dversion/$Aname/stable-1.0.1 ;' +{linebrake}#10 +
324 'make ;' +{linebrake}#10 +
325 'make install;' +{linebrake}#10 +
326 GetEnvironmentVariable('HOME') + '/' + WineUserFolder + '/wine/$Dname/$Dversion/$Aname/stable-1.0.1/bin/wineprefixcreate --prefix "' + GetEnvironmentVariable('HOME') + '/' + WineUserFolder + '/prefix/default/"' +{linebrake}#10 ;
328 {Create Script file}
329 if MakeFile((ConfigPath + '/SetupGit'),script) = true then
330 begin
332 {Set executable flag}
333 if SetExecutableFlag(ConfigPath + '/SetupGit') = false then
334 begin
335 RunYes := False ;
336 end;
338 if FileExistsAndIsExecutable('/usr/bin/gnome-terminal',false) = true then
339 begin
340 Terminal := 'gnome-terminal -x ';
342 else
343 begin
344 if FileExistsAndIsExecutable('/usr/bin/gnome-terminal',false) = true then
345 begin
346 Terminal := '/usr/bin/konsole -x ';
348 else
349 if FileExistsAndIsExecutable('/usr/bin/gnome-terminal',false) = true then
350 begin
351 Terminal := '/usr/bin/xterm ';
352 end;
353 end;
355 {Execute script one}
356 if RunYes = true then
357 begin
358 Log(0, ChannelLocal, 'Script One has being executed.');
359 Process.CommandLine := Terminal + ConfigPath +'/SetupGit';
360 Process.Execute;
361 end;
363 while Process.Running = true do
364 begin
365 sleep(5000);
366 end;
368 Result := Process.WaitOnExit;
370 end;
373 end;
375 function DirExistsIfNotMakeIt(Path:string; FolderName:string ): boolean;
377 LocalChannel:string; {Ignore this for now}
378 begin
379 LocalChannel := '';
381 if FolderName <> '' then
382 begin
383 if DirectoryExists( Path + FolderName ) = true then
384 begin
385 Log(0, LocalChannel, ('Directory' + Wrap( Path + FolderName ) + 'exists.')) ;
386 Result := true;
388 else
389 begin
390 Log(0, LocalChannel, ('Directory' + Wrap( Path + FolderName ) + ' does not exists.')) ;
391 if CreateDir( Path + FolderName ) then
392 begin
393 Log(0, LocalChannel, ('File' + Wrap( Path + FolderName ) + 'has being created.')) ;
394 Result := true;
396 else
397 begin
398 Log(0, LocalChannel, ('File' + Wrap( Path + FolderName ) + 'can not be created.')) ;
399 Result := true;
400 end;
401 end;
404 else
405 begin
406 Result := false;
407 end;
408 end;
410 function DirExistsIfNotMakeIt(PathWithFolder:string): boolean;
412 FolderPath:string;
413 FolderName:string;
414 begin
415 {E.G. PathWithFolder := '/home/test/hello/'.}
417 {If PathWithfolder has '/' at the end remove it.}
418 RemoveTrailingChars(PathWithFolder,['/']);
420 {FolderName := 'hello'.}
421 FolderName := ExtractFileName(PathWithFolder);
423 {FolderPath := '/home/test/'.}
424 FolderPath := ExtractFilePath(PathWithFolder);
426 {$IFDEF LogVar}
427 logVar(FolderName, 'FolderName');
428 logVar(FolderPath, 'FolderPath');
429 {$ENDIF}
431 {Pass the data to real function and get the result back.}
432 if DirExistsIfNotMakeIt(FolderPath, FolderName) = true then Result := true else Result := false;
433 end;
435 function MakeFile(FullPath:string;Data:string):boolean;
437 FD1:Cint;
438 CL:string;
439 begin
440 CL := 'MakeFile';
441 FpUnlink(FullPath);
443 FD1 := fpOpen (FullPath, O_WrOnly or O_Creat);
444 if FD1 > 0 then
445 begin
446 if length(Data)<>fpwrite (FD1,Data[1],Length(Data)) then
447 begin
448 Result := False ;
449 Log(1, CL, ('When writing to' + Wrap(FullPath)) );
451 else
452 begin
453 {$IFDEF MoreTrue }
454 Log(3, CL, ('File' + Wrap(FullPath) + 'has being created'));
455 {$ENDIF}
456 Result := true;
457 end;
458 fpClose(FD1);
459 end;
460 end;
462 function SetExecutableFlag(FullPath:string):boolean;
464 ChannelLocal:string;
465 begin
466 {770 is owner rwx, group rwx, other nothing}
467 if fpChmod (FullPath,&770) <> 0 then {0 = no error}
468 begin
469 Log(1, ChannelLocal, ('Can not set executable flag on' + Wrap(FullPath)) );
470 Result := False;
472 else
473 begin
474 {$IFDEF MoreTrue }
475 Log(0, ChannelLocal, ('Executable flag has being set on' + Wrap(FullPath)) );
476 {$ENDIF}
477 Result := true;
478 end;
479 end;
481 function ColourCheck(Input: TEdit):boolean;
483 LocalChannel:string;
484 temp:string;
485 begin
486 LocalChannel := 'ColourCheck';
487 {This does a CaseInsensitive check to see if the file exists. Wine does not care about the executable flag. }
488 {I can not find FindDiskFileCaseInsensitive in the doc.}
489 {If it can not find the file it will return nothing and it will clear the string.}
490 temp := WinToUnixPath(Input.Text);
492 if FindDiskFileCaseInsensitive(temp) <> '' then
493 begin
494 {$IFDEF MoreTrue}Log(3, LocalChannel, 'File' + Wrap(temp) + 'exists.');{$ENDIF}
495 Input.Font.Color := clgreen;
496 Result := true;
498 else
499 begin
500 Log(4, LocalChannel,'File' + Wrap(Input.Text) + 'does not exists.');
501 Input.Font.Color := clred;
502 Result := false;
503 end;
504 end;
506 function CutUpFlags(Flags:string):boolean;
508 Loop:integer;
509 Dump:integer;
510 Temp:string;
511 begin
512 UnitMain.form1.CheckListBox_Flags.Items.Clear;
514 for loop := 0 to ( WordCount( Flags, [';'] ) ) do
515 begin
516 Dump := FindPart( ';', Flags );
517 Temp := LeftStr( Flags, Dump - 1);
518 if Temp <> '' then UnitMain.form1.CheckListBox_Flags.Items.Add(Temp);
519 Delete(Flags, 1, (Dump)) ;
520 end;
521 if Flags <> '' then UnitMain.form1.CheckListBox_Flags.Items.Add(Flags);
523 end;
525 function FindPrefixInt(PrefixName:string):integer;
527 Loop:integer;
528 const
529 C = 'FindPrefixInt';
530 begin
531 {Error code is -1}
532 Result := -1;
534 for loop := 0 to (UnitMain.form1.ComboBox_PreFix.items.Count -1) do begin
535 if Data[loop].PrefixName = PrefixName then
536 begin
537 Result := loop;
538 exit;
539 end;
540 end;
542 if Result = -1 then log(1, C, ('Prefix' + Wrap(PrefixName) + 'does not exist.'));
543 end;
545 function GetWinFileName(FullPath:string):string;
546 begin
547 {Take path and return the file name only.}
548 {d:\Somefoldername\'Setup'.exe}
550 FullPath := AnsiReverseString(FullPath);
551 FullPath := Copy2Symb(FullPath, '\');
552 Copy2SymbDel(FullPath, '.');
553 FullPath := AnsiReverseString(FullPath);
555 Result := FullPath;
556 end;
558 end.