1;This file has been created by Adam Twardoch <adam@twardoch.com>
2;See README.TXT in this folder for instructions on building the setup
3
4[Setup]
5AppName=TTX
6AppVerName=TTX 2.0 r040926 for Windows
7AppPublisher=Just van Rossum
8AppPublisherURL=http://www.letterror.com/code/ttx/
9AppSupportURL=http://www.font.org/software/ttx/
10AppUpdatesURL=http://www.font.org/software/ttx/
11DefaultDirName={pf}\TTX
12DefaultGroupName=TTX
13AllowNoIcons=false
14LicenseFile=..\LICENSE.txt
15InfoBeforeFile=fonttools-win-setup.txt
16InfoAfterFile=..\Doc\changes.txt
17OutputBaseFilename=WinTTX2.0r040926
18AppCopyright=Copyright 1999-2004 by Just van Rossum, Letterror, The Netherlands.
19UninstallDisplayIcon={app}\ttx.ico
20
21[Tasks]
22Name: desktopicon; Description: Create a &desktop icon; GroupDescription: Additional icons:
23
24[Files]
25Source: ..\dist\ttx\*.*; DestDir: {app}; Flags: ignoreversion promptifolder
26Source: ..\LICENSE.txt; DestDir: {app}; Flags: ignoreversion promptifolder
27Source: ..\Doc\documentation.html; DestDir: {app}; Flags: ignoreversion promptifolder
28Source: ..\Doc\changes.txt; DestDir: {app}; Flags: ignoreversion promptifolder
29Source: ..\Doc\bugs.txt; DestDir: {app}; Flags: ignoreversion promptifolder
30Source: fonttools-win-setup.txt; DestDir: {app}; Flags: ignoreversion promptifolder
31Source: ttx.ico; DestDir: {app}; Flags: ignoreversion promptifolder; AfterInstall: AddFolderToPathVariable
32
33[Icons]
34Name: {userdesktop}\ttx.exe; Filename: {app}\ttx.exe; Tasks: desktopicon; IconFilename: {app}\ttx.ico; IconIndex: 0
35Name: {group}\TTX; Filename: {app}\ttx.exe; Tasks: desktopicon; IconFilename: {app}\ttx.ico; IconIndex: 0
36Name: {group}\TTX documentation; Filename: {app}\documentation.html; IconIndex: 0
37Name: {group}\Changes; Filename: {app}\changes.txt; IconIndex: 0
38Name: {group}\Bugs; Filename: {app}\bugs.txt; IconIndex: 0
39Name: {group}\License; Filename: {app}\LICENSE.txt; IconIndex: 0
40Name: {group}\Uninstall TTX; Filename: {uninstallexe}; IconIndex: 0
41Name: {reg:HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders,SendTo}\TTX; Filename: {app}\ttx.exe; WorkingDir: {reg:HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders,SendTo}; IconFilename: {app}\ttx.ico; IconIndex: 0; MinVersion: 0,5.00.2195
42
43[_ISTool]
44EnableISX=true
45
46[Registry]
47Root: HKCR; Subkey: .ttx; ValueType: string; ValueData: {reg:HKCR\.xml,}; Flags: createvalueifdoesntexist uninsdeletekey
48
49[Code]
50
51//
52// InnoSetup Extensions Knowledge Base
53// Article 44 - Native ISX procedures for PATH modification
54// http://www13.brinkster.com/vincenzog/isxart.asp?idart=44
55// Author: Thomas Vedel
56//
57
58// Version log:
59// 03/31/2003: Initial release (thv@lr.dk)
60
61const
62  // Modification method
63  pmAddToBeginning = $1;      // Add dir to beginning of Path
64  pmAddToEnd = $2;            // Add dir to end of Path
65  pmAddAllways = $4;          // Add also if specified dir is already included in existing path
66  pmAddOnlyIfDirExists = $8;  // Add only if specified dir actually exists
67  pmRemove = $10;             // Remove dir from path
68  pmRemoveSubdirsAlso = $20;  // Remove dir and all subdirs from path
69
70  // Scope
71  psCurrentUser = 1;          // Modify path for current user
72  psAllUsers = 2;             // Modify path for all users
73
74  // Error results
75  mpOK = 0;                   // No errors
76  mpMissingRights = -1;       // User has insufficient rights
77  mpAutoexecNoWriteacc = -2;  // Autoexec can not be written (may be readonly)
78  mpBothAddAndRemove = -3;    // User has specified that dir should both be removed from and added to path
79
80
81{ Helper procedure: Split a path environment variable into individual dirnames }
82procedure SplitPath(Path: string; var Dirs: TStringList);
83var
84  pos: integer;
85  s: string;
86begin
87  Dirs.Clear;
88  s := '';
89  pos := 1;
90  while (pos<=Length(Path)) do
91  begin
92    if (Path[pos]<>';') then
93      s := s + Path[pos];
94    if ((Path[pos]=';') or (pos=Length(Path))) then
95    begin
96      s := Trim(s);
97      s := RemoveQuotes(s);
98      s := Trim(s);
99      if (s <> '') then
100        Dirs.Add(s);
101      s := '';
102    end;
103    Pos := Pos + 1;
104  end;
105end; // procedure SplitPath
106
107
108{ Helper procedure: Concatenate individual dirnames into a path environment variable }
109procedure ConcatPath(Dirs: TStringList; Quotes: boolean; var Path: string);
110var
111  Index, MaxIndex: integer;
112  s: string;
113begin
114  MaxIndex := Dirs.Count-1;
115  Path := '';
116  for Index := 0 to MaxIndex do
117  begin
118    s := Dirs.Strings[Index];
119    if ((Quotes) and (pos(' ',s) > 0)) then
120      s := AddQuotes(s);
121    Path := Path + s;
122    if (Index < MaxIndex) then
123      Path := Path + ';'
124  end;
125end; // procedure ConcatPath
126
127
128{ Helper function: Modifies path environment string }
129procedure ModifyPathString(OldPath, DirName: string; Method: integer; Quotes: boolean; var ResultPath: string);
130var
131  Dirs: TStringList;
132  DirNotInPath: Boolean;
133  i: integer;
134begin
135  // Create Dirs variable
136  Dirs := TStringList.Create;
137
138  // Remove quotes form DirName
139  DirName := Trim(DirName);
140  DirName := RemoveQuotes(DirName);
141  DirName := Trim(DirName);
142
143  // Split old path in individual directory names
144  SplitPath(OldPath, Dirs);
145
146  // Check if dir is allready in path
147  DirNotInPath := True;
148  for i:=Dirs.Count-1 downto 0 do
149  begin
150    if (uppercase(Dirs.Strings[i]) = uppercase(DirName)) then
151      DirNotInPath := False;
152  end;
153
154  // Should dir be removed from existing Path?
155  if ((Method and (pmRemove or pmRemoveSubdirsAlso)) > 0) then
156  begin
157    for i:=Dirs.Count-1 downto 0 do
158    begin
159      if (((Method and pmRemoveSubdirsAlso) > 0) and (pos(uppercase(DirName)+'\', uppercase(Dirs.Strings[i])) = 1)) or
160         (((Method and (pmRemove) or (pmRemoveSubdirsAlso)) > 0) and (uppercase(DirName) = uppercase(Dirs.Strings[i])))
161      then
162        Dirs.Delete(i);
163    end;
164  end;
165
166  // Should dir be added to existing Path?
167  if ((Method and (pmAddToBeginning or pmAddToEnd)) > 0) then
168  begin
169    // Add dir to path
170    if (((Method and pmAddAllways) > 0) or DirNotInPath) then
171    begin
172      // Dir is not in path allready or should be added anyway
173      if (((Method and pmAddOnlyIfDirExists) = 0) or (DirExists(DirName))) then
174      begin
175        // Dir actually exsists or should be added anyway
176        if ((Method and pmAddToBeginning) > 0) then
177          Dirs.Insert(0, DirName)
178        else
179          Dirs.Append(DirName);
180      end;
181    end;
182  end;
183
184  // Concatenate directory names into one single path variable
185  ConcatPath(Dirs, Quotes, ResultPath);
186  // Finally free Dirs object
187  Dirs.Free;
188end; // ModifyPathString
189
190
191{ Helper function: Modify path on Windows 9x }
192function ModifyPath9x(DirName: string; Method: integer): integer;
193var
194  AutoexecLines: TStringList;
195  ActualLine: String;
196  PathLineNos: TStringList;
197  FirstPathLineNo: Integer;
198  OldPath, ResultPath: String;
199  LineNo, CharNo, Index: integer;
200
201  TempString: String;
202begin
203  // Expect everything to be OK
204  result := mpOK;
205
206  // Create stringslists
207  AutoexecLines := TStringList.Create;
208  PathLineNos := TStringList.Create;
209
210  // Read existing path
211  OldPath := '';
212  LoadStringFromFile('c:\Autoexec.bat', TempString);
213  AutoexecLines.Text := TempString;
214  PathLineNos.Clear;
215  // Read Autoexec line by line
216  for LineNo := 0 to AutoexecLines.Count - 1 do begin
217    ActualLine := AutoexecLines.Strings[LineNo];
218    // Check if line starts with "PATH=" after first stripping spaces and other "fill-chars"
219    if Pos('=', ActualLine) > 0 then
220    begin
221      for CharNo := Pos('=', ActualLine)-1 downto 1 do
222        if (ActualLine[CharNo]=' ') or (ActualLine[CharNo]=#9) then
223          Delete(ActualLine, CharNo, 1);
224      if Pos('@', ActualLine) = 1 then
225        Delete(ActualLine, 1, 1);
226      if (Pos('PATH=', uppercase(ActualLine))=1) or (Pos('SETPATH=', uppercase(ActualLine))=1) then
227      begin
228        // Remove 'PATH=' and add path to "OldPath" variable
229        Delete(ActualLine, 1, pos('=', ActualLine));
230        // Check if an earlier PATH variable is referenced, but there has been no previous PATH defined in Autoexec
231        if (pos('%PATH%',uppercase(ActualLine))>0) and (PathLineNos.Count=0) then
232          OldPath := ExpandConstant('{win}') + ';' + ExpandConstant('{win}')+'\COMMAND';
233        if (pos('%PATH%',uppercase(ActualLine))>0) then
234        begin
235          ActualLine := Copy(ActualLine, 1, pos('%PATH%',uppercase(ActualLine))-1) +
236                        OldPath +
237                        Copy(ActualLine, pos('%PATH%',uppercase(ActualLine))+6, Length(ActualLine));
238        end;
239        OldPath := ActualLine;
240
241        // Update list of line numbers holding path variables
242        PathLineNos.Add(IntToStr(LineNo));
243      end;
244    end;
245  end;
246
247  // Save first line number in Autoexec.bat which modifies path environment variable
248  if PathLineNos.Count > 0 then
249    FirstPathLineNo := StrToInt(PathLineNos.Strings[0])
250  else
251    FirstPathLineNo := 0;
252
253  // Modify path
254  ModifyPathString(OldPath, DirName, Method, True, ResultPath);
255
256  // Write Modified path back to Autoexec.bat
257  // First delete all existing path references from Autoexec.bat
258  Index := PathLineNos.Count-1;
259  while (Index>=0) do
260  begin
261    AutoexecLines.Delete(StrToInt(PathLineNos.Strings[Index]));
262    Index := Index-1;
263  end;
264  // Then insert new path variable into Autoexec.bat
265  AutoexecLines.Insert(FirstPathLineNo, '@PATH='+ResultPath);
266  // Delete old Autoexec.bat from disk
267  if not DeleteFile('c:\Autoexec.bat') then
268    result := mpAutoexecNoWriteAcc;
269  Sleep(500);
270  // And finally write Autoexec.bat back to disk
271  if not (result=mpAutoexecNoWriteAcc) then
272    SaveStringToFile('c:\Autoexec.bat', AutoexecLines.Text, false);
273
274  // Free stringlists
275  PathLineNos.Free;
276  AutoexecLines.Free;
277end; // ModifyPath9x
278
279
280{ Helper function: Modify path on Windows NT, 2000 and XP }
281function ModifyPathNT(DirName: string; Method, Scope: integer): integer;
282var
283  RegRootKey: integer;
284  RegSubKeyName: string;
285  RegValueName: string;
286  OldPath, ResultPath: string;
287  OK: boolean;
288begin
289  // Expect everything to be OK
290  result := mpOK;
291
292  // Initialize registry key and value names to reflect if changes should be global or local to current user only
293  case Scope of
294    psCurrentUser:
295      begin
296        RegRootKey := HKEY_CURRENT_USER;
297        RegSubKeyName := 'Environment';
298        RegValueName := 'Path';
299      end;
300    psAllUsers:
301      begin
302        RegRootKey := HKEY_LOCAL_MACHINE;
303        RegSubKeyName := 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment';
304        RegValueName := 'Path';
305      end;
306  end;
307
308  // Read current path value from registry
309  OK := RegQueryStringValue(RegRootKey, RegSubKeyName, RegValueName, OldPath);
310  if not OK then
311  begin
312    result := mpMissingRights;
313    Exit;
314  end;
315
316  // Modify path
317  ModifyPathString(OldPath, DirName, Method, False, ResultPath);
318
319  // Write new path value to registry
320  if not RegWriteStringValue(RegRootKey, RegSubKeyName, RegValueName, ResultPath) then
321  begin
322    result := mpMissingRights;
323    Exit;
324
325  end;
326end; // ModifyPathNT
327
328
329{ Main function: Modify path }
330function ModifyPath(Path: string; Method, Scope: integer): integer;
331begin
332  // Check if both add and remove has been specified (= error!)
333  if (Method and (pmAddToBeginning or pmAddToEnd) and (pmRemove or pmRemoveSubdirsAlso)) > 0 then
334  begin
335    result := mpBothAddAndRemove;
336    Exit;
337  end;
338
339  // Perform directory constant expansion
340  Path := ExpandConstantEx(Path, ' ', ' ');
341
342  // Test if Win9x
343  if InstallOnThisVersion('4,0','0,0') = irInstall then
344    ModifyPath9x(Path, Method);
345
346  // Test if WinNT, 2000 or XP
347  if InstallOnThisVersion('0,4','0,0') = irInstall then
348    ModifyPathNT(Path, Method, Scope);
349end; // ModifyPath
350
351procedure AddFolderToPathVariable();
352begin
353  ModifyPath('{app}', pmAddToBeginning, psAllUsers);
354  ModifyPath('{app}', pmAddToBeginning, psCurrentUser);
355end;
356