UnitMainBackend: Make the path to wine work when it has spaces in it.
[WineLauncher.git] / Functions / MainBackend / UnitMainBackend.pas
bloba7dd5357cf61526fb412db13a84b6555f1ce79e5
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 UnitMainBackend;
18 {$mode objfpc}{$H+}
20 interface
22 uses
23 Classes, SysUtils, XMLCfg, Process, BaseUnix, ComCtrls, Forms, Controls;
25 procedure SaveLastUsedConfig();
26 procedure LoadLastUsedConfig();
27 procedure OnWineVersionChange();
29 function RunWineCheck(ProgramNameOverRide:string; ProgramFlagsOverRide:string):boolean;
30 function ListProgramsOnDisc(ModeMe:TStrings; DriveChar:char):boolean;
31 function AddTabToPageControl(PageControl:TPageControl; caption:string):boolean;
32 function EmbedFrame(frame:TFrame; PageNumber:integer):boolean;
34 var
35 XmlLastUsedConfig:TXMLConfig;
36 LastUsedConfigLoading:boolean;
38 {The next three are used by ListProgramsOnDisc.}
39 LastReadLinkPath:string;
40 DiscErrorText:string;
41 OldPath:string;
43 implementation
44 uses
45 UnitInitialization,
46 UnitMain,
47 UnitMisc,
48 UnitSettings,
49 UnitProgramsList;
51 procedure SaveLastUsedConfig();
52 begin
53 if LastUsedConfigLoading = true then exit;
54 Try
55 {1}
56 XmlLastUsedConfig.SetValue('Version', '2');
57 {Was WineVersionInfo/DistributionName,DistributionVersion,Architecture.}
58 XmlLastUsedConfig.SetValue('WineVersionInfo/WineVersion', UnitMain.form1.ComboBox_WineVersion.Text);
59 {2}
60 XmlLastUsedConfig.SetValue('WineVersionInfo/UsesTerminal', UnitMain.form1.Check_Terminal.Checked);
61 XmlLastUsedConfig.SetValue('WineVersionInfo/UsesSoundWrapper', UnitMain.form1.CheckBox_UseSoundWrapper.Checked);
63 {Save}
64 XmlLastUsedConfig.Filename := (ConfigPath + '/LastUsedConfig.xml');
65 Finally
66 {Clean up}
67 XmlLastUsedConfig.Flush;
68 end;
69 end;
71 procedure LoadLastUsedConfig();
72 var
73 LastUsedConfigVersion:string;
74 begin
75 {Only run this ones wine has being scanned for.}
76 LastUsedConfigLoading := true;
77 XmlLastUsedConfig:= TXMLConfig.Create(nil);
79 Try
80 XmlLastUsedConfig.Filename := (ConfigPath + '/LastUsedConfig.xml');
81 {Get the version of the config file.}
82 LastUsedConfigVersion := XmlLastUsedConfig.GetValue('Version','');
83 {$IFDEF LogVar}
84 LogVar(LastUsedConfigVersion,'LastUsedConfigVersion');
85 {$ENDIF}
87 {Make sure the version value exists.}
88 if LastUsedConfigVersion = '-1' then
89 begin
90 Log(3, Channel, 'Invalided file version, never mind we ignore it and wirte over it.');
91 Exit();
92 end;
93 {1}
94 {Setting ItemIndex does not trigger OnEditingDone.}
95 {So we run Enter to update the list then we run EditingDone to check it}
97 SelectItem(UnitMain.form1.ComboBox_WineVersion, XmlLastUsedConfig.GetValue('WineVersionInfo/WineVersion', ''));
98 UnitMain.form1.ComboBox_WineVersionEnter(form1);
99 UnitMain.form1.ComboBox_WineVersionEditingDone(form1);
102 UnitMain.form1.Check_Terminal.Checked := XmlLastUsedConfig.GetValue('WineVersionInfo/UsesTerminal', false);
103 UnitMain.form1.CheckBox_UseSoundWrapper.Checked := XmlLastUsedConfig.GetValue('WineVersionInfo/UsesSoundWrapper', false);
105 Finally
106 XmlLastUsedConfig.Flush;
107 LastUsedConfigLoading := false;
108 end;
109 end;
111 function RunWineCheck(ProgramNameOverRide:string; ProgramFlagsOverRide:string):boolean;
113 loop:integer;
114 SoundWrapper:string;
115 temp00:integer;
116 WinePreFixRaw:string;
117 WinePreFix:string;
118 ChannelLocal:string;
119 ProgramFlags:string;
120 ProgramName:string;
121 WorkDir:string;
122 UnixPathWithOutFile:string;
123 WinePath:string; {~/.local/wine/[Wine Version]"}
124 begin
125 ChannelLocal := ('RunWineCheck');
127 WinePath := (PathToWine + UnitMain.form1.ComboBox_WineVersion.Text);
129 {Get wine version info}
130 wine_version_full := FindWine(WinePath);
131 if wine_version_full = '' then exit(false);
134 {Get Terminal info}
135 if UnitMain.form1.Check_Terminal.Checked = true then
136 begin
137 if UnitMain.form1.ComboBox_TerminalName.Text <> '' then
138 begin
139 temp00 := UnitMain.form1.ComboBox_TerminalName.ItemIndex;
140 RunIn := (UnitSettings.Form4.StringGrid_TerminalSettings.Cells[1,temp00] + ' ' + UnitSettings.Form4.StringGrid_TerminalSettings.Cells[2,temp00]);
141 Log(0, ChannelLocal, ('Using Terminal' + Wrap(RunIn)) );
142 end;
144 else
145 begin
146 {After the Program is closed the child process is still listed.}
147 RunIn := UnitSettings.Form4.ComboBox_ShellPath.text;
148 Log(0, ChannelLocal, ('Using' + Wrap(RunIn)) );
149 end;
151 {PreFix}
152 WinePreFixRaw := (PreFixList[1].Strings[UnitMain.form1.ComboBox_PreFix.ItemIndex]);
153 WinePreFix := ('env WINEPREFIX="' + WinePreFixRaw + '"');
154 {$IFDEF LogVar}
155 LogVar(WinePreFix, 'WinePreFix');
156 {$ENDIF}
159 {Sound Wrapper}
160 if UnitMain.form1.CheckBox_UseSoundWrapper.Checked = true then
161 begin
162 if FileExists(UnitMain.form1.ComboBox_SoundWrapper.Text) = true then
163 begin
164 SoundWrapper := (UnitMain.form1.ComboBox_SoundWrapper.Text + ' ');
165 Log(0, ChannelLocal, ('File' + Wrap(UnitMain.form1.ComboBox_SoundWrapper.Text) + 'exists'));
167 else
168 begin
169 Log(1, ChannelLocal, ('File' + Wrap(UnitMain.form1.ComboBox_SoundWrapper.Text) + 'does not exists'));
170 exit(false);
171 end;
173 else
174 begin
175 Log(0, ChannelLocal, ('No sound wrapper will be used'));
176 end;
178 {Set program flags}
179 if ProgramNameOverRide = '' then
180 begin
181 if UnitMain.form1.EditBox_ProgramPath.Text <> '' then
182 begin
183 ProgramFlags := '';
184 for loop := 0 to (UnitMain.form1.CheckListBox_Flags.Items.Count) do
185 begin
186 if UnitMain.form1.CheckListBox_Flags.Checked[loop] = true then
187 begin
188 ProgramFlags := (ProgramFlags + ' ' + UnitMain.form1.CheckListBox_Flags.Items.ValueFromIndex[loop]);
189 end;
190 end;
191 {$IFDEF LogVar}
192 LogVar(ProgramFlags, 'ProgramFlags' );
193 {$ENDIF}
194 ProgramName := (' ' + '"' + UnitMain.form1.EditBox_ProgramPath.Text + '"' + ProgramFlags + ' ');
196 else
197 begin
198 Log(1, ChannelLocal, ('Please select a program.'));
199 exit(false);
200 end;
202 else
203 begin
204 ProgramName := (' ' + '"' + ProgramNameOverRide + '"' + ProgramFlagsOverRide + ' ');
205 end;
207 {Set the WorkDir}
208 UnixPathWithOutFile := ExtractFilePath(WinToUnixPath(UnitMain.form1.EditBox_ProgramPath.Text));
209 if ProgramNameOverRide = '' then
210 begin
211 if DoesFolderExists(ExtractFilePath(UnixPathWithOutFile), ExtractFileName(UnixPathWithOutFile)) then
212 begin
213 WorkDir := WorkDirTemplate(GetUnixDirPath(WinToUnixPath(UnitMain.form1.EditBox_ProgramPath.Text)) );
215 else
216 begin
217 WorkDir := WorkDirTemplate(WinePreFixRaw + '/dosdevices/c:/windows');
218 end;
220 else
221 begin
222 WorkDir := WorkDirTemplate(WinePreFixRaw + '/dosdevices/c:/windows');
223 end;
225 {Setup start_S1}
226 start_S1 := ('#! /bin/sh' + {linebrake}#10 + WorkDir {Line brake done in template.} + WinePreFix + SoundWrapper + ' "' + wine_version_full + '" ' + ProgramName + ';');
227 {$IFDEF LogVar}
228 LogVar(start_S1, 'start_S1');
229 {$ENDIF}
231 {Create Script file}
232 if MakeFile((ConfigPath + '/1'), start_S1) = false then
233 begin
234 log(1, ChannelLocal, ('Can not make file' + wrap(ConfigPath + '/1')) );
235 exit(false);
236 end;
238 {Set executable flag}
239 if SetExecutableFlag(ConfigPath + '/1') = false then
240 begin
241 log(1, ChannelLocal, ('Can not set executable flag on file'+ wrap(ConfigPath + '/1')) );
242 exit(false)
243 end;
245 {Execute script one}
246 Log(0, ChannelLocal, ('Script One has being executed.'));
247 AProcess.CommandLine := (RunIn + ' ' + ConfigPath +'/1');
248 {After the Program is closed the child process is still listed.}
249 AProcess.Execute;
250 Result := true;
251 end;
253 function ListProgramsOnDisc(ModeMe:TStrings; DriveChar:char):boolean;
255 script:string;
256 Path:string;
257 Info:TSearchRec;
258 Count:Longint;
259 FindPath:string;
260 begin
261 {TODO : This function needs to check the drive not just the folders.}
262 Path := (PathToPrefix + UnitMain.Form1.ComboBox_PreFix.Text + '/dosdevices/' + AnsiLowerCase(DriveChar));
264 {Do not rescan if the path is the same as the last one.}
265 {Note if you change disks it will not rescan it.}
266 if OldPath = Path then exit(false);
268 if AsyncProcessScan.Active = false then
269 begin
270 OldPath := Path;
271 ModeMe.Clear;
272 LastReadLinkPath := fpReadLink(Path + ':');
274 else exit(false);
276 if LastReadLinkPath = '' then
277 begin
278 log(4, '',('Link ' + Wrap(Path + ':') + 'does not exists.'));
279 LastReadLinkPath := '';
280 DiscErrorText := 'Please map' + wrap(DriveChar + ':') + 'to your cd / dvd drive, You can do that in winecfg.';
281 exit(false);
282 end;
284 {Reset count.}
285 Count := 0;
286 if FindFirst((Path + ':/*'), faAnyFile and faDirectory, Info) = 0 then
287 begin
288 Repeat
289 Inc(Count);
290 Until FindNext(info) <> 0;
291 if Count < 3 then
292 begin
293 log(0,'', Info.Name);
294 DiscErrorText := 'You have no disc in your drive.';
295 LastReadLinkPath := '';
296 exit(false);
297 end;
298 end;
299 FindClose(Info);
301 if LastReadLinkPath = '/' then
302 begin
303 DiscErrorText := 'You can not map '+ DriveChar + ': to root.';
304 LastReadLinkPath := '';
305 exit(false);
306 end;
308 if LastReadLinkPath = GetEnvironmentVariable('HOME') then
309 begin
310 DiscErrorText := 'You can not map '+ DriveChar + ': to your home folder.';
311 LastReadLinkPath := '';
312 exit(false);
313 end;
315 FindPath := SearchForBin('find');
316 if FindPath = '' then
317 begin
318 DiscErrorText := ('Can not find the program called' + Wrap('find'));
319 LastReadLinkPath := '';
320 exit(false);
321 end;
323 script := (FindPath + ' -H ' + Path + ': -iname *.exe');
324 Log(0, '', 'Script Scan has being executed.');
325 AsyncProcessScan.CommandLine := script;
326 AsyncProcessScan.Execute;
327 DiscErrorText := 'Scaning';
328 Timer.Enabled := true;
330 Result := true;
332 end;
334 procedure OnWineVersionChange();
335 begin
336 if UnitMain.form1.ComboBox_WineVersion.Text <> '' then
337 begin
338 UnitMain.form1.Btn_Run.Enabled := true;
340 else
341 UnitMain.form1.Btn_Run.Enabled := false;
342 end;
344 function AddTabToPageControl(PageControl:TPageControl; caption:string):boolean;
346 Index:Integer;
347 begin
348 Index := PageControl.PageCount ;
349 SetLength(TabSheets, (Index + 1));
351 {Make tab sheet.}
352 TabSheets[Index] := TTabSheet.Create(TabSheets[Index]);
353 TabSheets[Index].Caption := caption;
354 TabSheets[Index].PageControl := PageControl;
355 end;
357 function EmbedFrame(frame:TFrame; PageNumber:integer):boolean;
358 begin
359 frame.Parent := UnitMain.form1.PageControl1.Page[PageNumber];
360 frame.Align := (alclient);
361 frame.Show;
362 end;
364 end.